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

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代码运行次数:0运行复制

xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">

4.0.0

org.springframework.boot

spring-boot-starter-parent

2.2.2.RELEASE

com.shxt

nemt

0.0.1-SNAPSHOT

war

某项目api接口

某项目api接口

UTF-8

UTF-8

2.2.1.RELEASE

1.2.60

1.8

org.springframework.boot

spring-boot-dependencies

${spring.boot.version}

pom

import

org.apache.commons

commons-lang3

com.alibaba

fastjson

${fastjson.version}

org.springframework.boot

spring-boot-starter-web

org.minbox.framework

api-boot-starter-swagger

org.springframework.boot

spring-boot-starter-tomcat

provided

org.apache.httpcomponents

httpclient

mysql

mysql-connector-java

org.minbox.framework

api-boot-starter-datasource-switch

org.minbox.framework

api-boot-starter-http-converter

org.minbox.framework

api-boot-starter-security-oauth-jwt

org.minbox.framework

api-boot-starter-mybatis-enhance

org.springframework.boot

spring-boot-starter-test

test

org.junit.vintage

junit-vintage-engine

org.minbox.framework

api-boot-dependencies

2.2.1.RELEASE

pom

import

3.3 配置application.properties

大多数默认配置就行

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

配置springboot相关内容

代码语言:javascript代码运行次数:0运行复制spring.application.name=项目名配置swagger在线文档的内容

代码语言:javascript代码运行次数:0运行复制# 接口文档相关

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代码运行次数:0运行复制#安全配置相关

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代码运行次数:0运行复制# 数据库相关

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=root3.4 配置curd代码生成插件

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

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

代码语言:javascript代码运行次数:0运行复制

org.springframework.boot

spring-boot-maven-plugin

org.minbox.framework

api-boot-mybatis-enhance-maven-codegen

2.1.5.RELEASE

mysql

mysql-connector-java

5.1.47

generator

true

nemt

jdbc:mysql://localhost:3306

root

root

com.djy.shxt.nemt

代码语言:javascript代码运行次数:0运行复制reimport之后可以看到这里多了一个插件 双击之后,就会在这个路径生成两类文件

一类是实体类

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

如果不是则使用KeyGeneratorTypeEnum.UUID

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

代码语言:javascript代码运行次数:0运行复制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代码运行次数:0运行复制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 {

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代码运行次数:0运行复制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 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代码运行次数:0运行复制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代码运行次数:0运行复制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代码运行次数:0运行复制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 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代码运行次数:0运行复制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 {

/**

* 根据用户登录名查询用户信息

*

* @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代码运行次数:0运行复制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---

Copyright © 2022 世界杯吉祥物_世界杯日本队 - ctpapi.com All Rights Reserved.