如何去开发一个springboot starter

如何去开发一个springboot starter

我们在平时用 Java 开发的时候,在 pom.xml 文件中引入一个依赖就可以很方便的使用了,但是你们知道这是如何实现的吗。

现在我们就来解决这一个问题!

创建 SpringBoot 项目

首先我们要做的就是把你想要给别人方便使用的内容自己的写好

我这里直接另外创建了一个 springboot 的 web 项目,在这个 web 项目中我用 controller 写了几个简单的接口,用于后面的调用,然后再创建一个 springboot 项目,这个新的 springboot 项目就是用来开发 starter 的方便使用者更好、更方便使用。

现在是具体流程:

springboot 的 web 项目创建

用 IDEA 快速创建一个 springboot 项目,创建方法如下:

  1. 选择 spring Initializer
  2. 自己写一个项目的名称
  3. 语言选择 Java
  4. 包管理工具选择 Maven
  5. 组这个可以自己写 例如我的昵称 xwhking 就可以写 com.xwkhing
  6. jdk 选择1.8
  7. Java 选择8
  8. 然后就是下一步

如何去开发一个springboot starter_第1张图片

进入下一步后

  1. 选择 springboot 的版本,我一般选择2.7左右的

  2. 然后选择开发工具

    1. Spring Boot Devtools
    2. Spring COnfiguration Processor 主要用于后面我们在工程中使用的使用在 yml 中写配置时能够自动提示配置
    3. Lombok 通过使用 annotation 快速的生成主要的 getter 和 setter
    4. Spring Web 加上也没事
      如何去开发一个springboot starter_第2张图片
  3. 然后就是创建了。

创建好了以后就进入写代码环节,写一个简单的 web 请求的 Demo

我这里的目录结构如下:

如何去开发一个springboot starter_第3张图片

UserController的代码如下:
package com.xwhking.interface_test.controller;


import com.xwhking.interface_test.entity.User;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import java.util.Date;

import static com.xwhking.interface_test.utils.GenSign.genSign;

@RestController
@RequestMapping("/user")
public class UserController {
    @GetMapping("/name")
    public String getName(@RequestParam String name , HttpServletRequest request){
        System.out.println("请求参数名字为 : " + name);
        return "GET 请求参数名字为 : " + name;
    }
    @GetMapping("/getOne")
    public User getUser(HttpServletRequest request){
        User user = new User();
        user.setId(123l);
        user.setUsername("xwhking");
        user.setPassword("admin123");
        System.out.println(user);
        return user ;
    }
}
User代码
package com.xwhking.interface_test.entity;

import lombok.Data;

@Data
public class User {
    private Long id;
    private String username;
    private String password;
    @Override
    public String toString(){
        return "User { " +
                "id: " + id + "," +
                "name:" + username + ","+
                "password: " + password + "}";
    }
}

这些完成以后就可以启动这一个项目了。

可以用浏览器试试

如何去开发一个springboot starter_第4张图片

starter开发

以同样的方式创建一个springboot项目,需要特别注意的就是,我们需要把 pom.xml 文件中的 build 部分代码全部去掉

pom.xml 文件

注意这里引入了 Hutool 工具库,用于后面开发,并且文件里面是没有 build 模块的,这里还需要注意把版本的snapshot去掉


<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.0modelVersion>
    <parent>
        <groupId>org.springframework.bootgroupId>
        <artifactId>spring-boot-starter-parentartifactId>
        <version>2.7.10version>
        <relativePath/> 
    parent>
    <groupId>com.xwhkinggroupId>
    <artifactId>InterfaceStarterartifactId>
    <version>0.0.1version>
    <name>InterfaceStartername>
    <description>InterfaceStarterdescription>
    <properties>
        <java.version>8java.version>
    properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-starter-webartifactId>
        dependency>

        <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-devtoolsartifactId>
            <scope>runtimescope>
            <optional>trueoptional>
        dependency>
        <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-configuration-processorartifactId>
            <optional>trueoptional>
        dependency>
        <dependency>
            <groupId>org.projectlombokgroupId>
            <artifactId>lombokartifactId>
            <optional>trueoptional>
        dependency>
        <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-starter-testartifactId>
            <scope>testscope>
        dependency>
        <dependency>
            <groupId>cn.hutoolgroupId>
            <artifactId>hutool-allartifactId>
            <version>5.8.16version>
        dependency>
    dependencies>
project>

目录结构
  1. client 目录 这里就是真正使用的类,对对应的功能进行了封装。
  2. config 目录 这里对 client 进行配置,并且把 client 包装成一个 Bean 返回
  3. utils 工具类,这里用来生成签名的工具
  4. META-INF.spring.factories 这个非常重要,用于别人调用的时候,在写配置的之后能够进行提示与自动装配

如何去开发一个springboot starter_第5张图片

client 代码
package com.xwhking.interfacestarter.client;

import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpUtil;
import lombok.Data;

import java.time.LocalDateTime;
import java.util.Date;
import java.util.HashMap;

import static com.xwhking.interfacestarter.utils.GenSign.genSign;

/**
 * 发起请求时候一定要注意,不要把secretKey直接传送,只需要进行一个签名传送就好了,然后后端通过同样的方式进行签名
 * 的生成,进行对比,验证身份。
 */
@Data
public class XWHKINGClient {
    private String accessKey;
    private String secretKey;
    private Long userId;
    public XWHKINGClient(String accessKey,String secretKey,Long userId){
        this.userId = userId;
        this.accessKey = accessKey;
        this.secretKey = secretKey;
    }
    public String getName(String name){
        //可以单独传入http参数,这样参数会自动做URL编码,拼接在URL中
        HashMap<String, Object> paramMap = new HashMap<>();
        paramMap.put("name", name);
        HashMap<String,String> headerMap = new HashMap<>();
        headerMap.put("accessKey",accessKey);
        headerMap.put("userId",userId.toString());
        headerMap.put("sign", genSign(accessKey,secretKey,userId));
        headerMap.put("timestamp",Long.toString(new Date().getTime()));
        String result1= HttpRequest.get("http://localhost:8080/user/name")
                .addHeaders(headerMap)
                .form(paramMap).execute().body();
        System.out.println(result1);
        return result1;
    }
    public String GetUser(){
        HashMap<String,String> headerMap = new HashMap<>();
        headerMap.put("accessKey",accessKey);
        headerMap.put("userId",userId.toString());
        headerMap.put("sign", genSign(accessKey,secretKey,userId));
        headerMap.put("timestamp",Long.toString(new Date().getTime()));
        String result1= HttpRequest.get("http://localhost:8080/user/getOne")
                .addHeaders(headerMap)
                .execute().body();
        System.out.println(result1);
        return result1;
    }

    public static void main(String[] args) {
    new XWHKINGClient("xwhking","admin123",123123l).getName("XWHKING");
    }
}

这里都加了请求头,加请求头的目的是为了,进行签名认证。

为什么要进行签名认证
  1. 保证安全性,一个人不能随便调用,如果随便调用的话,自己的服务器资源会收到压迫,以及资源的损失。
  2. 适用于无需保存登录态。只认签名,不关注用户登录态。
如何进行签名认证

通过 http request header 头传递参数

这里主要传递的参数

  • accessKey: 调用的标识, 需要复杂、 无序、无规律,这里我没有实现,只是简单的模拟,如果需要实现的话可以使用现成的签名实现工具包,例如 hutool
  • secretKey: 调用的密钥,需要复杂、 无序、无规律,该参数一定一定不能放到请求头中,不然可能会被别人抓包,以及可能造成泄露。
  • 用户请求的参数
  • sign: 签名,由 accessKey 和 secretKey 以及 userId 等信息生成,用于传递信息。然后后端通过同样的方式进行生成对比验证权限。
  • 上述问题满足了,可能还抵挡不了别人的攻击,例如别人用重放就可以再次调用 API 了,限制重放的方法:
    • 加随机数,只能使用一次,服务端要保存使用过的随机数
    • 加 timestamp 时间戳,检验时间戳是否过期,我这里就是通过时间戳,超过10s就失效。
对web中的UserController进行更新

更新就是为了校验,然后如果更新了,项目记得重启

package com.xwhking.interface_test.controller;


import com.xwhking.interface_test.entity.User;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import java.util.Date;

import static com.xwhking.interface_test.utils.GenSign.genSign;

@RestController
@RequestMapping("/user")
public class UserController {
    /**
     * 校验签名,以及其他信息,注意这里的 secretKey 是模拟的一般用户的 secretKey 是需要去从数据库取出来,
     * 然后进行验证。
     * @param request
     */
    private void verifyRequest(HttpServletRequest request){
        String sign = request.getHeader("sign");
        String accessKey = request.getHeader("accessKey");
        String secretKey = "admin123";
        String userId = request.getHeader("userId");
        String requestTime = request.getHeader("timestamp");
        long oldTime = Long.parseLong(requestTime);
        long newTime = new Date().getTime();
        if(newTime - oldTime > 10000){
            throw new RuntimeException("检测到请求异常");
        }
        String newSign = genSign(accessKey,secretKey,Long.parseLong(userId));
        if(!newSign.equals(sign)){
            throw new RuntimeException("签名错误");
        }
    }
    @GetMapping("/name")
    public String getName(@RequestParam String name , HttpServletRequest request){
        verifyRequest(request);
        System.out.println("请求参数名字为 : " + name);
        return "GET 请求参数名字为 : " + name;
    }
    @GetMapping("/getOne")
    public User getUser(HttpServletRequest request){
        verifyRequest(request);
        User user = new User();
        user.setId(123l);
        user.setUsername("xwhking");
        user.setPassword("admin123");
        System.out.println(user);
        return user ;
    }
}

config 代码

要注意其中的注解

package com.xwhking.interfacestarter.config;

import com.xwhking.interfacestarter.client.XWHKINGClient;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@ConfigurationProperties(prefix = "xwhking.client")
@Data
@ComponentScan
public class XWHKINGClientConfig {
    private String accessKey;
    private String secretKey;
    private String userId;
    @Bean
    public XWHKINGClient xwhkingClient(){
        return new XWHKINGClient(accessKey,secretKey,Long.parseLong(userId));
    }
}

生成签名代码

这里直接使用了 Hutool 工具库中的 sh256 的生成方法

package com.xwhking.interfacestarter.utils;

import cn.hutool.crypto.SecureUtil;
import lombok.Data;


@Data
public class GenSign {
    public static String genSign(String accessKey,String secretKey,Long userId){
        String key = "xwhking" + "." + accessKey + "." + secretKey + "."  + userId;
        return SecureUtil.sha256(key);
    }
}

META-INF 中文件的内容

通过看内容就可以看出,你需要把后面的内容进行替换,写入你的地址。

org.springframework.boot.autoconfigure.EnableAutoConfiguration = com.xwhking.interfacestarter.XWHKINGClientConfig

到这里 Starter 就完了,然后使用 maven 进行打包(调用install)。这里的打包会把包直接放入你的 maven 仓库,打包成功就会出现 BUILD SUCCESS

如何去开发一个springboot starter_第6张图片

在其他项目中使用

首先复制这段代码

<groupId>com.xwhkinggroupId>
<artifactId>InterfaceStarterartifactId>
<version>0.0.1version>

然后在你的其他项目中添加进依赖

<dependency>
	<groupId>com.xwhkinggroupId>
    <artifactId>InterfaceStarterartifactId>
    <version>0.0.1version>
dependency>

刷新 maven 仓库

然后再 yml 配置中加入配置

在 config中的prefix 可以设置前缀,也就是可以更改xwhking.client

如何去开发一个springboot starter_第7张图片

然后在你的代码中使用 Test 进行测试

@SpringBootTest
class MainApplicationTests {

    @Resource
    private XWHKINGClient xwhkingClient;

    @Test
    void testClient(){
        xwhkingClient.getName("xwhking") ;
    }

}

调用结果:

出来了 xwhking 结果成功。

如何去开发一个springboot starter_第8张图片

这样开发一个starter 就结束了

你可能感兴趣的:(spring,boot,后端,java)