前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【ApiBoot】墙裂推荐!从此不怕接口开发

【ApiBoot】墙裂推荐!从此不怕接口开发

作者头像
你好戴先生
发布2020-09-03 15:28:20
8111
发布2020-09-03 15:28:20
举报
文章被收录于专栏:戴言泛滥戴言泛滥

1.

首先,ApiBoot是一个开源框架

官方网站是:http://apiboot.minbox.io

ApiBoot™ 基于SpringBoot为接口服务而生,组件化Api的首选落地解决方案

最近有一个项目需要开发api接口

顺手在码云搜索了一下

第一眼就看到了这个项目

大概看了看文档,感觉真心不错

就开始用这个搭建框架,进行开发了

项目很完善,框架几乎可以做到0代码搭建

2.

很快,接口系统框架就搭建好了

这个框架的功能很多

我根据项目的需要整合了swagger、Security、OAuth、Data Switch、Mybatis Enhance、Mybatis Enhance Codegen六个模块

主要实现了在线接口文档、Oauth2.0授权认证机制、MySQL数据库操作、curd代码生成功能

个人还是认为:写代码跟做事一样,合适最重要

不一定非得用最负责最高级最完美的实现,合适就好

鉴于很多人可能没什么耐心把全部内容看完

我把代码共享到了码云上边,连接地址在这

https://gitee.com/daijiyong/apiboot-test.git

效果图如下:

3. 下面说说怎么具体实现的

官方文档:

http://apiboot.minbox.io/zh-cn/docs/introduce.html

3.1 创建springboot项目

浏览器输入地址:https://start.spring.io/

填写参数,我选择的是war包形式发布

点击生成代码

然后作为maven项目将代码导入idea

3.2 配置pom.xml文件

代码语言:javascript
复制
<?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>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.2.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.shxt</groupId>
<artifactId>nemt</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>war</packaging>
<name>某项目api接口</name>
<description>某项目api接口</description>


<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<spring.boot.version>2.2.1.RELEASE</spring.boot.version>
<fastjson.version>1.2.60</fastjson.version>
<java.version>1.8</java.version>
</properties>


<dependencies>
<!--SpringBoot Dependencies-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring.boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>


<!-- 阿里JSON解析器 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>${fastjson.version}</version>
</dependency>


<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.minbox.framework</groupId>
<artifactId>api-boot-starter-swagger</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<!--            <version>4.4</version>-->
</dependency>
<!--MySQL-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<!--ApiBoot DataSource Switch-->
<dependency>
<groupId>org.minbox.framework</groupId>
<artifactId>api-boot-starter-datasource-switch</artifactId>
</dependency>
<!--ApiBoot Http Converter-->
<dependency>
<groupId>org.minbox.framework</groupId>
<artifactId>api-boot-starter-http-converter</artifactId>
</dependency>


<!--ApiBoot Security Oauth-->
<dependency>
<groupId>org.minbox.framework</groupId>
<artifactId>api-boot-starter-security-oauth-jwt</artifactId>
</dependency>
<!--ApiBoot Mybatis Enhance-->
<dependency>
<groupId>org.minbox.framework</groupId>
<artifactId>api-boot-starter-mybatis-enhance</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.minbox.framework</groupId>
<artifactId>api-boot-dependencies</artifactId>
<version>2.2.1.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
</project>

3.3 配置application.properties 大多数默认配置就行

一些个性化的东西需要自己配置

配置springboot相关内容

代码语言:javascript
复制
spring.application.name=项目名

配置swagger在线文档的内容

代码语言:javascript
复制
# 接口文档相关
api.boot.swagger.title=某项目
api.boot.swagger.version=V1.0
api.boot.swagger.description=某项目api接口文档,接口遵循restful设计规范,返回数据均为json
api.boot.swagger.base-package=com.djy.shxt.nemt.api
api.boot.swagger.contact.name=戴先生
api.boot.swagger.contact.email=
api.boot.swagger.contact.website=
api.boot.swagger.license=
api.boot.swagger.license-url=

配置token认证授权机制参数

代码语言:javascript
复制
#安全配置相关
api.boot.security.away=jdbc
api.boot.security.enable-default-store-delegate=false
api.boot.oauth.clients[0].client-id=daijiyong
api.boot.oauth.clients[0].client-secret=nemt
api.boot.oauth.clients[0].grant-types=password,refresh_token

配置数据库参数

代码语言:javascript
复制
# 数据库相关
api.boot.datasource.hikari.master.url=jdbc:mysql://localhost:3306/nemt?characterEncoding=utf8&serverTimezone=Asia/Shanghai
api.boot.datasource.hikari.master.username=root
api.boot.datasource.hikari.master.password=root

3.4 配置curd代码生成插件

在pom.xml文件中添加如下配置内容

其中com.djy.shxt.nemt是生成代码的路径

代码语言:javascript
复制
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>

<plugin>
<groupId>org.minbox.framework</groupId>
<artifactId>api-boot-mybatis-enhance-maven-codegen</artifactId>
<version>2.1.5.RELEASE</version>
<dependencies>
<!--数据驱动依赖-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.47</version>
</dependency>
</dependencies>
<executions>
<execution>
<goals>
<goal>generator</goal>
</goals>
</execution>
</executions>
<configuration>
<execute>true</execute>
<dbName>nemt</dbName>
<dbUrl>jdbc:mysql://localhost:3306</dbUrl>
<dbUserName>root</dbUserName>
<dbPassword>root</dbPassword>
<packageName>com.djy.shxt.nemt</packageName>
</configuration>
</plugin>
</plugins>
</build>
代码语言:javascript
复制
reimport之后可以看到这里多了一个插件 

双击之后,就会在这个路径生成两类文件

一类是实体类

@Id的主键生成策略,会根据表内主键是否定义了自增来进行判断,如果是自增使用KeyGeneratorTypeEnum.AUTO

如果不是则使用KeyGeneratorTypeEnum.UUID

如果你项目内是自定义的主键,可以进行修改为KeyGeneratorTypeEnum.DIY。

代码语言:javascript
复制
package com.djy.shxt.nemt.enity;


import com.gitee.hengboy.mybatis.enhance.common.annotation.Column;
import com.gitee.hengboy.mybatis.enhance.common.annotation.Id;
import com.gitee.hengboy.mybatis.enhance.common.annotation.Table;
import com.gitee.hengboy.mybatis.enhance.common.enums.KeyGeneratorTypeEnum;
import lombok.Data;


import java.io.Serializable;


/**
 * 
 * @author ApiBoot Mybatis Enhance Codegen
 */
@Data
@Table(name = "speciality_post")
public class SpecialityPost implements Serializable {


/**
     * 
     */
    @Id(generatorType = KeyGeneratorTypeEnum.AUTO)
    @Column(name = "id")
    private Integer id;
/**
     * 
     */
    @Column(name = "area")
    private String area;
/**
     * 
     */
    @Column(name = "school")
    private String school;
/**
     * 
     */
    @Column(name = "degree")
    private String degree;
/**
     * 
     */
    @Column(name = "original_speciality")
    private String originalSpeciality;
/**
     * 
     */
    @Column(name = "speciality")
    private String speciality;
/**
     * 
     */
    @Column(name = "original_post")
    private String originalPost;
/**
     * 
     */
    @Column(name = "post")
    private String post;
/**
     * 
     */
    @Column(name = "number")
    private Integer number;
}

二类是动态查询实体

代码语言:javascript
复制
package com.djy.shxt.nemt.dsl;


import com.djy.shxt.nemt.enity.SpecialityPost;
import com.gitee.hengboy.mybatis.enhance.dsl.expression.ColumnExpression;
import com.gitee.hengboy.mybatis.enhance.dsl.expression.TableExpression;


/**
 * @author ApiBoot Mybatis Enhance Codegen
 */
public class DSpecialityPost extends TableExpression<SpecialityPost> {


public DSpecialityPost(String root) {
super(root);
    }


public static DSpecialityPost DSL() {
return new DSpecialityPost("speciality_post");
    }


/**
     *
     */
public ColumnExpression id = new ColumnExpression("id", this);
/**
     *
     */
public ColumnExpression area = new ColumnExpression("area", this);
/**
     *
     */
public ColumnExpression school = new ColumnExpression("school", this);
/**
     *
     */
public ColumnExpression degree = new ColumnExpression("degree", this);
/**
     *
     */
public ColumnExpression originalSpeciality = new ColumnExpression("original_speciality", this);
/**
     *
     */
public ColumnExpression speciality = new ColumnExpression("speciality", this);
/**
     *
     */
public ColumnExpression originalPost = new ColumnExpression("original_post", this);
/**
     *
     */
public ColumnExpression post = new ColumnExpression("post", this);
/**
     *
     */
public ColumnExpression number = new ColumnExpression("number", this);


@Override
public ColumnExpression[] getColumns() {
return new ColumnExpression[]{id, area, school, degree, originalSpeciality, speciality, originalPost, post, number};
    }


}

把这两类文件放到对应的包下

使用动态查询实体示例

代码语言:javascript
复制
package com.djy.shxt.nemt.service;


import com.djy.shxt.nemt.dsl.DSpecialityPost;
import com.djy.shxt.nemt.enity.SpecialityPost;
import com.djy.shxt.nemt.mapper.ISpecialityPost;
import com.gitee.hengboy.mybatis.enhance.dsl.factory.EnhanceDslFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;


import java.util.List;


@Service
@Transactional(rollbackFor = Exception.class)
public class SpecialityPostService {
@Autowired
    ISpecialityPost iSpecialityPost;
@Autowired
private EnhanceDslFactory dslFactory;


public Long countAll() {
return iSpecialityPost.countAll();
    }


public List<SpecialityPost> selectBySchool(String school) {
        DSpecialityPost dSpecialityPost = DSpecialityPost.DSL();


return dslFactory.createSearchable()
                .selectFrom(dSpecialityPost)
                .where(dSpecialityPost.school.like("", school, "%"))
                .resultType(SpecialityPost.class)
                .fetch();
    }
}

至此,通过自动生成的curd代码做数据库的读写就完成了

3.5 整合Spring Security的JDBC方式获取AccessToken

ApiBoot Security内部提供了两种方式进行读取需要认证的用户信息,

ApiBoot Security使用内存方式(memory)不写一行代码就可以实现用户的

认证并获取AccessToken

我使用JDBC方式实现了,其他方式可以看一下官方文档

数据库方式(jdbc)是将用户信息保存到数据库内,ApiBoot Security定义了一个默

认表结构的用户信息数据表,我们可以从官网找到建表语句直接在自己的数据库内创建即可,当然如果不使用默认的表结构可以进行自定义读取用户信息。

注意:在数据库内存放用户的密码必须是通过BCryptPasswordEncoder加密后的密文字符串。

3.5.1 创建默认用户表结构

我们在数据库内创建一张名为system_user的系统用户信息表,表结构如下所示:

代码语言:javascript
复制
CREATE TABLE `system_user` (
`su_id` varchar(36) COLLATE utf8mb4_general_ci NOT NULL COMMENT '用户编号',
`su_login_name` varchar(30) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '登录名',
`su_nick_name` varchar(30) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '昵称',
`su_password` varchar(200) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '用户密码',
`su_create_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`su_status` int(11) DEFAULT '1' COMMENT '用户状态,1:正常,0:冻结,-1:已删除',
  PRIMARY KEY (`su_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='系统用户信息表';

system_user用户表创建完成后,我们往这张表内添加一条用户数据,如下所示

代码语言:javascript
复制
INSERT INTO `system_user` VALUES ('9b69fd26-14db-11ea-b743-dcd28627348e','dai','你好戴先生','$2a$10$RbJGpi.v3PwkjrYENzOzTuMxazuanX3Qa2hwI/f55cYsZhFT/nX3.','2019-12-02 08:13:22',1);

在登录时用户名对应su_login_name字段,而密码则是对应su_password字段,dai这个用户的密码初始化为123456,密码的格式必须为BCryptPasswordEncoder加密后的密文。

实体类可以使用代码生成工具生成

针对system_user表我们需要来创建一个ApiBoot MyBatis Enhance使用的实体,创建一个名为SystemUser的实体如下所示:

代码语言:javascript
复制
package com.djy.shxt.nemt.enity;


import com.gitee.hengboy.mybatis.enhance.common.annotation.Column;
import com.gitee.hengboy.mybatis.enhance.common.annotation.Id;
import com.gitee.hengboy.mybatis.enhance.common.annotation.Table;
import com.gitee.hengboy.mybatis.enhance.common.enums.KeyGeneratorTypeEnum;
import lombok.Data;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;


import java.util.Collection;
import java.util.Collections;


/**
 * @author daijiyong
 */
@Data
@Table(name = "system_user")
public class SystemUser implements UserDetails {
/**
     * 用户编号
     */
@Id(generatorType = KeyGeneratorTypeEnum.UUID)
@Column(name = "su_id")
private String userId;
/**
     * 登录名
     */
@Column(name = "su_login_name")
private String loginName;
/**
     * 昵称
     */
@Column(name = "su_nick_name")
private String nickName;
/**
     * 密码
     */
@Column(name = "su_password")
private String password;
/**
     * 创建时间
     */
@Column(name = "su_create_time")
private String createTime;
/**
     * 用户状态
     * 1:正常,0:已冻结,-1:已删除
     */
@Column(name = "su_status")
private Integer status;


@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return Collections.EMPTY_LIST;
    }


@Override
public String getUsername() {
return this.loginName;
    }


@Override
public String getPassword() {
return this.password;
    }


/**
     * UserDetails提供的方法,用户是否未过期
     * 可根据自己用户数据表内的字段进行扩展,这里为了演示配置为true
     *
     * @return
     */
@Override
public boolean isAccountNonExpired() {
return true;
    }


/**
     * UserDetails提供的方法,用户是否未锁定
     * 可根据自己用户数据表内的字段进行扩展,这里为了演示配置为true
     *
     * @return
     */
@Override
public boolean isAccountNonLocked() {
return true;
    }


/**
     * UserDetails提供的方法,凭证是否未过期
     * 可根据自己用户数据表内的字段进行扩展,这里为了演示配置为true
     *
     * @return
     */
@Override
public boolean isCredentialsNonExpired() {
return true;
    }


/**
     * UserDetails提供的方法,是否启用
     *
     * @return
     */
@Override
public boolean isEnabled() {
return this.status == 1;
    }
}

具体的注解使用详见ApiBoot MyBatis Enhance文档

这里还一点需要注意的是,SystemUser实现了UserDetails接口

如果使用过Spring Security的同学应该都知道这是Spring Security提供的用户详情接口定义

我们如果自定义查询用户就应该让我们自定义的用户实体(注:这是的自定义用户实体也就是SystemUser实体)实现这个接口并全部实现UserDetails接口内提供的方法。

创建用户数据接口

代码语言:javascript
复制
package com.djy.shxt.nemt.mapper;


import com.djy.shxt.nemt.enity.SystemUser;
import com.gitee.hengboy.mybatis.enhance.mapper.EnhanceMapper;
import org.apache.ibatis.annotations.Param;


/**
 * @author daijiyong
 */
public interface ISystemUserMapper extends EnhanceMapper<SystemUser, String> {


/**
     * 根据用户登录名查询用户信息
     *
     * @param loginName {@link SystemUser#getLoginName()}
     * @return {@link SystemUser}
     */
SystemUser findByLoginName(@Param("loginName") String loginName);
}

该接口继承了EnhanceMapper接口,可以自动被扫描到创建代理的实例后并且加入IOC,这样我们在项目其他的地方可以直接注入使用。

注意:findByXxx方法是ApiBoot MyBatis Enhance提供的方法命名规则查询,多个查询条件可以使用And或者Or追加,会自动根据方法的规则生成对应的SQL。

实现ApiBootStoreDelegate接口

ApiBoot Security提供了一个接口ApiBootStoreDelegate,这个接口主要是用来查询登录用户的具体信息的作用

当我们通过grant_type=password&username=xxx的方式进行获取AccessToken时,ApiBoot Security会直接把username的参数值传递给ApiBootStoreDelegate#loadUserByUsername的方法内

这样我们就可以根据username进行查询用户并返回给ApiBoot Security做后续的认证操作。

代码语言:javascript
复制
package com.djy.shxt.nemt.service;


import com.alibaba.fastjson.JSON;
import com.djy.shxt.nemt.mapper.ISystemUserMapper;
import org.apache.commons.lang3.ObjectUtils;
import org.minbox.framework.api.boot.plugin.security.delegate.ApiBootStoreDelegate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;


@Service
public class SystemUserService implements ApiBootStoreDelegate {
/**
     * logger instance
     */
static Logger logger = LoggerFactory.getLogger(SystemUserService.class);
/**
     * 用户数据接口
     */
    @Autowired
private ISystemUserMapper mapper;


    @Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
UserDetails userDetails = mapper.findByLoginName(username);
if (ObjectUtils.isEmpty(userDetails)) {
throw new UsernameNotFoundException("用户:" + username + ",不存在.");
        }
        logger.info("登录用户的信息:{}", JSON.toJSONString(userDetails));
return userDetails;
    }
}

3.6 运行项目,测试接口 测试token生成

使用postman进行post请求方式测试

跟三个参数grant_type、username、password

分别对应application配置文件中的api.boot.oauth.clients[0].grant-types=password,refresh_token

以及数据表中的登录名和密码

以下配置对应application配置文件中的 api.boot.oauth.clients[0].client-id=daijiyong api.boot.oauth.clients[0].client-secret=nemt

点击send就能顺利获取到token和refreshToken,以及他们的有效期

更新token使用下面的方式

测试接口,如果没有输入token,提示未认证

点击接口右边的锁形按钮

将获取到的这两个参数,拼接一下 "tokenType": "bearer", "value": "a84e887b-9b51-4180-acbc-e281e7d322e6"

点击Authorize按钮

再点击execute,成功,有数据返回了

4.框架完成,可以快(ku)乐(bi)的写代码了

文/戴先生@2020年6月15日

---end---

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2020-06-15,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 你好戴先生 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
数据库
云数据库为企业提供了完善的关系型数据库、非关系型数据库、分析型数据库和数据库生态工具。您可以通过产品选择和组合搭建,轻松实现高可靠、高可用性、高性能等数据库需求。云数据库服务也可大幅减少您的运维工作量,更专注于业务发展,让企业一站式享受数据上云及分布式架构的技术红利!
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档