本篇文章是《自己动手实现一个好用的SpringBoot后端框架》系列的第二篇文章
上一篇地址:《(一)自己动手实现一个好用的SpringBoot后端框架(项目搭建、组件依赖)》
上一篇讲到了配置文件的部分,接下来我们继续讲组件具体怎么在代码中集成和配置
下面关于配置的部分,我们统一放在/src/main/java/com/yinchd/web/config
目录中
1、ConfigCenter
配置中心,我们将Druid的配置信息配置在其中
package com.yinchd.web.config;
import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.sql.DataSource;
/**
* 配置中心
*/
@Configuration
public class ConfigCenter {
/**
* Druid数据源配置
*/
@Bean
@ConfigurationProperties(prefix = "spring.datasource.druid")
public DataSource druidDataSource() {
return new DruidDataSource();
}
}
接下来我们把代码生成工具集成进来
2、CodeGenerator
CodeGenerator
的集成方法我在另一篇文章:《自己动手实现一个好用的MybatisPlus代码生成器》 中有详解,建议大家参照文章进行集成,这里我就不再细述
用户表结构
CREATE TABLE `sys_user` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '编号',
`account` varchar(50) CHARACTER SET utf8 NOT NULL COMMENT '账号',
`user_name` varchar(50) NOT NULL COMMENT '姓名',
`password` varchar(100) NOT NULL COMMENT '密码',
`avatar` varchar(200) DEFAULT NULL COMMENT '头像',
`sex` int(1) DEFAULT '1' COMMENT '用户性别(1男 2女)',
`email` varchar(100) DEFAULT NULL COMMENT '邮箱',
`mobile` varchar(11) DEFAULT NULL COMMENT '手机号',
`telephone` varchar(15) DEFAULT NULL COMMENT '座机号码',
`nation` varchar(10) CHARACTER SET utf8 DEFAULT '汉族' COMMENT '民族',
`status` int(1) NOT NULL DEFAULT '1' COMMENT '状态(0:禁用 1:正常)',
`dept` varchar(1024) DEFAULT NULL COMMENT '用户所属部门,多个部门id之间用|线分隔',
`create_by` varchar(50) CHARACTER SET utf8 DEFAULT 'admin' COMMENT '创建人',
`create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`last_update_by` varchar(50) DEFAULT NULL COMMENT '更新人',
`last_update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`del_flag` int(1) DEFAULT '0' COMMENT '逻辑删除(0未删,1已删)',
PRIMARY KEY (`id`) USING BTREE,
UNIQUE KEY `idx_account` (`account`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC COMMENT='用户管理'
id为主键,account我设置了唯一索引,用户表大家可以根据实际情况来设计,不一定是这些字段
这里我插入一条管理员数据,密码我使用了加密算法进行加密,加密算法我后面会讲,大家先照样子初始化一条
INSERT INTO `sys_user`(`id`, `account`, `user_name`, `password`, `avatar`, `sex`, `email`, `mobile`, `telephone`, `nation`, `status`, `dept`, `create_by`, `create_time`, `last_update_by`, `last_update_time`, `del_flag`) VALUES (1, 'admin', '管理员', '$2a$10$7LKovEeC0DfPCNKuBNMOtuaWpT13Lvkm7CQU5kngEOIWXf830i/Cq', '', 1, '', '', NULL, '汉族', 1, '', 'admin', '2020-02-13 08:20:22', 'admin', '2021-03-29 14:15:37', 0);
接下来我们使用上一步的CodeGenerator
来生成用户相关的代码
在CodeGenerator的main方法的配置好要生成的表信息
public static void main(String[] args) {
// 待生成的表名
String tableName = "sys_user";
// 生成的时候要去掉的表前缀,如果不需要去除什么前缀,则这里为空就行
String trimTablePrefix = "sys_";
// 生成文件的父包路径
String codeGeneratePath = "com.yinchd.web";
System.out.println("开始生成如下表:" + tableName + " 到 " + codeGeneratePath + " 目录中...");
// 后面三个boolean值分别代表是否生成Controller、Service、Dao和实体,有时我们改了表结构,这里可以方便控制生成哪些,不生成哪些
generate(tableName, trimTablePrefix, codeGeneratePath, true, true, true);
System.out.println("生成成功...");
}
生成效果如下
可以看到成功生成了Model
、Controller
、Service
、Mapper
、Xml
等文件
接下来我们在Controller里写个接口测试一下能否查到数据,能查到数据证明项目基础框架搭建成功
UserController
package com.yinchd.web.controller;
import com.yinchd.web.model.UserModel;
import com.yinchd.web.service.UserService;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
/**
*
* 用户管理 前端控制器
*
*
* @author yinchd
* @since 2021-04-25
*/
@RestController
@RequestMapping("user")
public class UserController {
@Resource
UserService userService;
@GetMapping("get")
public UserModel getUser() {
return userService.getById(1);
}
}
我们把项目跑起来测试一下,运行入口类WebBootApplication
的main方法启动项目
看到成功运行了项目,项目运行在520端口,我们去浏览器中调一下UserController中刚建的测试接口
在浏览器地址栏输入如下地址
http://localhost:520/user/get
结果如下
可以看到成功的返回了数据库里的我们初始化的这条数据
但是在实际项目开发中,我们不可能写完一个接口直接给前端,让前端自己去看接口中字段的含义,特别是当接口很多的时候,如果没有一个统一的接口管理界面就不是很方便
Swagger就是为了解决这个问题而设计的,只要我们在接口上加上一些注解说明,项目启动的时候Swagger就会自动去帮我们生成接口信息,很是方便
下一步我们就把Swagger给集成进来
4、集成Swagger
这里我们使用Swagger的最新版,3.x的版本
package com.yinchd.web.config;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.Contact;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
/**
* Swagger配置
*/
@Configuration
public class SwaggerConfig {
/**
* 控制swagger是否开启,开关在application.yml文件中,
* 上线后可以在配置文件中将开关改为false,这样线上就不会生成swagger文档了
*/
@Value("${web.swagger.enable}")
private final boolean swaggerEnabled = true;
@Bean
public Docket createRestApi() {
return new Docket(DocumentationType.OAS_30)
.apiInfo(apiInfo())
.enable(swaggerEnabled)
.select()
.apis(RequestHandlerSelectors.basePackage("com.yinchd.web"))
.paths(PathSelectors.any())
.build()
.pathMapping("/");
}
private ApiInfo apiInfo() {
return new ApiInfoBuilder().title("WebBoot统一API服务")
.contact(new Contact("yinchd", "#", "[email protected]"))
.version("v1.0")
.build();
}
}
我们来改造一下UserController,将Swagger注解添加进来,这样我们就可以让Swagger帮我们生成API接口文档
package com.yinchd.web.controller;
import com.yinchd.web.model.UserModel;
import com.yinchd.web.service.UserService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
/**
*
* 用户管理 前端控制器
*
*
* @author yinchd
* @since 2021-04-25
*/
@RestController
@RequestMapping("user")
@Api(tags = "用户管理")
@Slf4j
public class UserController {
@Resource
UserService userService;
@GetMapping("get")
@ApiOperation("用户列表")
public UserModel getUser() {
log.info("查询用户列表");
return userService.getById(1);
}
}
改完后要重启一下项目,重启完成后,我们在浏览器地址栏中输入swagger的地址
http://localhost:520/swagger-ui/index.html
(注意:swagger 3.x版本请求地址和2.x请求地址有些不一样,当然2.x的请求地址在这里也能请求成功,不过返回还是2.x版本的UI界面,而3.x是新的UI界面,新界面如下图)
可以看到Swagger自动帮我们把接口列表生成出来了,我们来调用测试一下
注:如果后端只需要用到单体架构(中小型项目),使用基于cookie-session + jsp或者thymeleaf的方案,至此我们只需要再集成一些其它组件就可以专注于业务开发了
接下来我们可以把用户模块的列表、新增、修改、删除、禁用等功能快速写出来,如果对MybatisPlus的使用不熟的同学可以顺便拿用户模块的CRUD练练手,后面讲用户权限设计的时候,用户模块我会重新设计
当我们在用户模块中写了一堆接口后,我们是不是会想:咦,这些接口好像都可以被人直接调用,似乎不太安全,我们能不能想一个方式来解决这个问题呢?
这里可以回顾一下,之前我们做项目,如果是基于cookie-session模式的项目,在用户登录成功后,我们可以把用户信息存在session中,用户接下来的请求,我们都先检查一下session中有没有登录成功的用户信息,如果有,则证明此次请求合法,如果没有,则代表未登录或者没有权限,在前后端分离的项目中,session方案似乎就不太适用了,那我们应该怎么做呢?
这个时候我们可以想到使用token令牌的方式,比如jwt来生成token令牌(对jwt不了解的同学先百度了解一下,或者看我这篇文章里的大致介绍),用户登录成功后,我们颁发一个带过期时间的凭证(token)给用户,用户接下来的请求中,每次都必须在请求头中带上这个凭证(token),我们从凭证(token)中解析出用户信息,如果凭证(token)没过期且能解析出用户信息,则代表此次请求合法,反之则代表没登录或者不合法
目前我们先不考虑通过角色权限来更细粒度的控制接口权限,我们暂且先只通过token来控制接口访问,后续文章中我会将角色权限这添加进来配合jwt token一起来实现接口权限控制
本篇就暂且讲到这里,下一节我们来讲jwt怎么在本项目中具体使用
上一篇地址:《(一)自己动手实现一个好用的SpringBoot后端框架(项目搭建、组件依赖)》