脚手架 base-sys
0.简介
1.基于SpringBoot+MybatisPlus-Plus的快速开发脚手架,具有完整的权限管理功能,前端使用Vue;
2.技术选型:
SpringBoot 2.7.0 容器+MVC框架
SpringSecurity 5.7.1 认证和授权框架
MyBatis 3.5.9 ORM框架
MyBatis-Plus 3.5.1 MyBatis增强工具
MyBatis-Plus Generator 3.5.1 数据层代码生成器
Swagger-UI 3.0.0 文档生产工具
Redis 6.0 分布式缓存
Docker 20.10 应用容器引擎
Druid 1.2.9 数据库连接池
Hutool 5.8.0 Java工具类库
JWT 0.9.1 JWT登录支持
Lombok 1.18.24 简化对象封装工具
1.搭建项目
1.1 创建表
/*
Navicat Premium Data Transfer
Source Server : localhost
Source Server Type : MySQL
Source Server Version : 50560
Source Host : localhost:3306
Source Schema : mall_tiny
Target Server Type : MySQL
Target Server Version : 50560
File Encoding : 65001
Date: 14/09/2022 23:38:47
*/
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
-- ----------------------------
-- Table 1 structure for sys_admin
-- ----------------------------
DROP TABLE IF EXISTS `sys_admin`;
CREATE TABLE `sys_admin` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`username` varchar(64) DEFAULT NULL,
`password` varchar(64) DEFAULT NULL,
`icon` varchar(500) DEFAULT NULL COMMENT '头像',
`email` varchar(100) DEFAULT NULL COMMENT '邮箱',
`nick_name` varchar(200) DEFAULT NULL COMMENT '昵称',
`note` varchar(500) DEFAULT NULL COMMENT '备注信息',
`create_time` datetime DEFAULT NULL COMMENT '创建时间',
`login_time` datetime DEFAULT NULL COMMENT '最后登录时间',
`status` int(1) DEFAULT '1' COMMENT '帐号启用状态:0->禁用;1->启用',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=16 DEFAULT CHARSET=utf8 COMMENT='后台用户表';
-- ----------------------------
-- Records of sys_admin
-- ----------------------------
INSERT INTO `sys_admin` VALUES (1, 'admin', '$2a$10$.Xgy4yCIJhBSTIR1EsHL.O4lI63fi3kwMDzDZQI3tibQZ3GUa6iyC', 'http://macro-oss.oss-cn-shenzhen.aliyuncs.com/mall/images/20180607/timg.jpg', '[email protected]', '系统管理员', '系统管理员', '2022-09-14 13:32:47', '2022-09-14 12:45:16', 1);
-- ----------------------------
-- Table 2 structure for sys_admin_login_log
-- ----------------------------
DROP TABLE IF EXISTS `sys_admin_login_log`;
CREATE TABLE `sys_admin_login_log` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`admin_id` bigint(20) DEFAULT NULL,
`create_time` datetime DEFAULT NULL,
`ip` varchar(64) DEFAULT NULL,
`address` varchar(100) DEFAULT NULL,
`user_agent` varchar(100) DEFAULT NULL COMMENT '浏览器登录类型',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=287 DEFAULT CHARSET=utf8 COMMENT='后台用户登录日志表';
-- ----------------------------
-- Records of sys_admin_login_log
-- ----------------------------
-- ----------------------------
-- Table 3 structure for sys_admin_role_relation
-- ----------------------------
DROP TABLE IF EXISTS `sys_admin_role_relation`;
CREATE TABLE `sys_admin_role_relation` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`admin_id` bigint(20) DEFAULT NULL,
`role_id` bigint(20) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=40 DEFAULT CHARSET=utf8 COMMENT='后台用户和角色关系表';
-- ----------------------------
-- Records of sys_admin_role_relation
-- ----------------------------
INSERT INTO `sys_admin_role_relation` VALUES (1, 1, 1);
-- ----------------------------
-- Table 4 structure for sys_menu
-- ----------------------------
DROP TABLE IF EXISTS `sys_menu`;
CREATE TABLE `sys_menu` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`parent_id` bigint(20) DEFAULT NULL COMMENT '父级ID',
`title` varchar(100) DEFAULT NULL COMMENT '菜单名称',
`level` int(4) DEFAULT NULL COMMENT '菜单级数',
`sort` int(4) DEFAULT NULL COMMENT '菜单排序',
`name` varchar(100) DEFAULT NULL COMMENT '前端名称',
`icon` varchar(200) DEFAULT NULL COMMENT '前端图标',
`hidden` int(1) DEFAULT NULL COMMENT '前端隐藏',
`create_time` datetime DEFAULT NULL COMMENT '创建时间',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=29 DEFAULT CHARSET=utf8 COMMENT='后台菜单表';
-- ----------------------------
-- Records of sys_menu
-- ----------------------------
INSERT INTO `sys_menu` VALUES (1, 0, '系统设置', 0, 0, 'ums', 'ums', 0, '2022-09-14 16:29:13');
INSERT INTO `sys_menu` VALUES (2, 1, '用户列表', 1, 0, 'admin', 'ums-admin', 0, '2022-09-14 16:29:51');
INSERT INTO `sys_menu` VALUES (3, 1, '角色列表', 1, 0, 'role', 'ums-role', 0, '2022-09-14 16:30:13');
INSERT INTO `sys_menu` VALUES (4, 1, '菜单列表', 1, 0, 'menu', 'ums-menu', 0, '2022-09-14 16:30:53');
INSERT INTO `sys_menu` VALUES (5, 1, '资源列表', 1, 0, 'resource', 'ums-resource', 0, '2022-09-14 16:31:13');
-- ----------------------------
-- Table 5 structure for sys_resource
-- ----------------------------
DROP TABLE IF EXISTS `sys_resource`;
CREATE TABLE `sys_resource` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`name` varchar(200) DEFAULT NULL COMMENT '资源名称',
`url` varchar(200) DEFAULT NULL COMMENT '资源URL',
`description` varchar(500) DEFAULT NULL COMMENT '描述',
`category_id` bigint(20) DEFAULT NULL COMMENT '资源分类ID',
`create_time` datetime DEFAULT NULL COMMENT '创建时间',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=32 DEFAULT CHARSET=utf8 COMMENT='后台资源表';
-- ----------------------------
-- Records of sys_resource
-- ----------------------------
INSERT INTO `sys_resource` VALUES (1, '后台用户管理', '/admin/**', '', 4, '2022-09-14 16:47:34');
INSERT INTO `sys_resource` VALUES (2, '后台角色管理', '/role/**', '', 4, '2022-09-14 16:48:24');
INSERT INTO `sys_resource` VALUES (3, '后台菜单管理', '/menu/**', '', 4, '2022-09-14 16:48:48');
INSERT INTO `sys_resource` VALUES (4, '资源分类管理', '/resourceCategory/**', '', 4, '2022-09-14 16:49:18');
INSERT INTO `sys_resource` VALUES (5, '后台资源管理', '/resource/**', '', 4, '2022-09-14 16:49:45');
-- ----------------------------
-- Table 6 structure for sys_resource_category
-- ----------------------------
DROP TABLE IF EXISTS `sys_resource_category`;
CREATE TABLE `sys_resource_category` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`name` varchar(200) DEFAULT NULL COMMENT '分类名称',
`sort` int(4) DEFAULT NULL COMMENT '排序',
`create_time` datetime DEFAULT NULL COMMENT '创建时间',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=9 DEFAULT CHARSET=utf8 COMMENT='资源分类表';
-- ----------------------------
-- Records of sys_resource_category
-- ----------------------------
INSERT INTO `sys_resource_category` VALUES (1, '商品模块', 0, '2022-09-14 10:21:44');
INSERT INTO `sys_resource_category` VALUES (2, '订单模块', 0, '2022-09-14 10:22:34');
INSERT INTO `sys_resource_category` VALUES (3, '营销模块', 0, '2022-09-14 10:22:48');
INSERT INTO `sys_resource_category` VALUES (4, '权限模块', 0, '2022-09-14 10:23:04');
INSERT INTO `sys_resource_category` VALUES (5, '内容模块', 0, '2022-09-14 16:34:27');
INSERT INTO `sys_resource_category` VALUES (6, '其他模块', 0, '2022-09-14 16:35:49');
-- ----------------------------
-- Table 7 structure for sys_role
-- ----------------------------
DROP TABLE IF EXISTS `sys_role`;
CREATE TABLE `sys_role` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`name` varchar(100) DEFAULT NULL COMMENT '名称',
`description` varchar(500) DEFAULT NULL COMMENT '描述',
`admin_count` int(11) DEFAULT NULL COMMENT '后台用户数量',
`status` int(1) DEFAULT '1' COMMENT '启用状态:0->禁用;1->启用',
`sort` int(11) DEFAULT '0',
`create_time` datetime DEFAULT NULL COMMENT '创建时间',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=9 DEFAULT CHARSET=utf8 COMMENT='后台用户角色表';
-- ----------------------------
-- Records of sys_role
-- ----------------------------
INSERT INTO `sys_role` VALUES (1, '超级管理员', '拥有所有查看和操作功能', 0, 1, 0, '2022-09-14 15:11:05');
-- ----------------------------
-- Table 8 structure for sys_role_menu_relation
-- ----------------------------
DROP TABLE IF EXISTS `sys_role_menu_relation`;
CREATE TABLE `sys_role_menu_relation` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`role_id` bigint(20) DEFAULT NULL COMMENT '角色ID',
`menu_id` bigint(20) DEFAULT NULL COMMENT '菜单ID',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=111 DEFAULT CHARSET=utf8 COMMENT='后台角色菜单关系表';
-- ----------------------------
-- Records of sys_role_menu_relation
-- ----------------------------
INSERT INTO `sys_role_menu_relation` VALUES (1, 1, 1);
INSERT INTO `sys_role_menu_relation` VALUES (2, 1, 2);
INSERT INTO `sys_role_menu_relation` VALUES (3, 1, 3);
INSERT INTO `sys_role_menu_relation` VALUES (4, 1, 4);
INSERT INTO `sys_role_menu_relation` VALUES (5, 1, 5);
-- ----------------------------
-- Table 9 structure for sys_role_resource_relation
-- ----------------------------
DROP TABLE IF EXISTS `sys_role_resource_relation`;
CREATE TABLE `sys_role_resource_relation` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`role_id` bigint(20) DEFAULT NULL COMMENT '角色ID',
`resource_id` bigint(20) DEFAULT NULL COMMENT '资源ID',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=216 DEFAULT CHARSET=utf8 COMMENT='后台角色资源关系表';
-- ----------------------------
-- Records of sys_role_resource_relation
-- ----------------------------
INSERT INTO `sys_role_resource_relation` VALUES (1, 1, 1);
INSERT INTO `sys_role_resource_relation` VALUES (2, 1, 2);
INSERT INTO `sys_role_resource_relation` VALUES (3, 1, 3);
INSERT INTO `sys_role_resource_relation` VALUES (4, 1, 4);
INSERT INTO `sys_role_resource_relation` VALUES (5, 1, 5);
SET FOREIGN_KEY_CHECKS = 1;
1.2 说明
说明:
1. 角色role为基准,分别和用户admin、菜单menu、资源resource 关联;
2. 角色role、用户admin、两者关系表admin_role_relation
3. 角色role、菜单menu、 两者关系表role_menu_relation
4. 角色role、资源resource、两者关系表role_resource_relation
5. 其他的表:用户登录日志admin_login_log、资源分类resource_category
1. 默认的数据有:
角色sys_role:超级管理员(1)
用户sys_admin:系统管理员admin(1)
用户角色关联表:(1,1,1);
菜单sys_menu:系统设置、用户列表、角色列表、菜单列表、资源列表
角色菜单关联表:(... 5个数据);
资源sys_resource:后台用户管理、后台角色管理、后台菜单管理、资源分类管理、后台资源管理
角色资源关联表:(... 5个数据);
资源分类:几个分类;
2. 还有别的方式:用户 --- 角色 --- 权限 (功能少一些)
1.3 环境搭建
数据库MySQL、缓存Redis:https://www.cnblogs.com/lailix/p/16650703.html
1.4 创建项目,添加依赖
<?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>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.0</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>org.example</groupId>
<artifactId>base-sys</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<!--SpringBoot通用依赖模块-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!--lombok依赖-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<!--SpringBoot校验框架-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
<!--SpringBoot配置处理-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<!--集成druid连接池-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.2.9</version>
</dependency>
<!--MyBatis Plus 依赖-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.1</version>
</dependency>
<!--MyBatis Plus 代码生成器-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-generator</artifactId>
<version>3.5.1</version>
</dependency>
<!--Velocity模板引擎-->
<dependency>
<groupId>org.apache.velocity</groupId>
<artifactId>velocity-engine-core</artifactId>
<version>2.3</version>
</dependency>
<!--redis依赖配置-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!--Swagger-UI API文档生产工具-->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-boot-starter</artifactId>
<version>3.0.0</version>
</dependency>
<!--Hutool Java工具包-->
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.8.0</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
1.5 代码生成器
- 使用MybatisPlus 自带的生成代码功能,生成controller、service、mapper、model、mapper.xml等代码,无需手动创建
package org.example.generator;
import cn.hutool.core.util.StrUtil;
import cn.hutool.setting.dialect.Props;
import com.baomidou.mybatisplus.core.exceptions.MybatisPlusException;
import com.baomidou.mybatisplus.generator.AutoGenerator;
import com.baomidou.mybatisplus.generator.config.*;
import com.baomidou.mybatisplus.generator.config.po.LikeTable;
import com.baomidou.mybatisplus.generator.config.querys.MySqlQuery;
import com.baomidou.mybatisplus.generator.config.rules.DateType;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
import com.baomidou.mybatisplus.generator.engine.VelocityTemplateEngine;
import java.util.Collections;
import java.util.Scanner;
/**
* MyBatisPlus代码生成器
*/
public class MyBatisPlusGenerator {
public static void main(String[] args) {
String projectPath = System.getProperty("user.dir");
String moduleName = scanner("模块名");
String[] tableNames = scanner("表名,多个英文逗号分割").split(",");
// 代码生成器
AutoGenerator autoGenerator = new AutoGenerator(initDataSourceConfig());
autoGenerator.global(initGlobalConfig(projectPath));
autoGenerator.packageInfo(initPackageConfig(projectPath, moduleName));
autoGenerator.template(initTemplateConfig());
autoGenerator.strategy(initStrategyConfig(tableNames));
autoGenerator.injection(initInjectionConfig(projectPath, moduleName));
autoGenerator.execute(new VelocityTemplateEngine());
}
//读取控制台内容信息
private static String scanner(String tip) {
Scanner scanner = new Scanner(System.in);
System.out.println(("请输入" + tip + ":"));
if (scanner.hasNext()) {
String next = scanner.next();
if (StrUtil.isNotEmpty(next)) {
return next;
}
}
throw new MybatisPlusException("请输入正确的" + tip + "!");
}
//初始化数据源配置
private static DataSourceConfig initDataSourceConfig() {
Props props = new Props("generator.properties");
String url = props.getStr("dataSource.url");
String username = props.getStr("dataSource.username");
String password = props.getStr("dataSource.password");
return new DataSourceConfig.Builder(url, username, password).dbQuery(new MySqlQuery()).build();
}
//初始化全局配置
private static GlobalConfig initGlobalConfig(String projectPath) {
return new GlobalConfig.Builder()
.outputDir(projectPath + "/src/main/java")
.author("java")
.disableOpenDir()
.enableSwagger()
.fileOverride()
.dateType(DateType.ONLY_DATE).build();
}
//初始化包配置
private static PackageConfig initPackageConfig(String projectPath, String moduleName) {
Props props = new Props("generator.properties");
return new PackageConfig.Builder()
.moduleName(moduleName)
.parent(props.getStr("package.base"))
.entity("model")
.pathInfo(Collections.singletonMap(OutputFile.mapperXml, projectPath + "/src/main/resources/mapper/" + moduleName))
.build();
}
//初始化模板配置
private static TemplateConfig initTemplateConfig() {
//可以对controller、service、entity模板进行配置
TemplateConfig.Builder builder = new TemplateConfig.Builder();
return builder
.controller("template/controller.java.vm")
.build();
}
//初始化策略配置
private static StrategyConfig initStrategyConfig(String[] tableNames) {
StrategyConfig.Builder builder = new StrategyConfig.Builder();
builder.entityBuilder()
.naming(NamingStrategy.underline_to_camel)
.columnNaming(NamingStrategy.underline_to_camel)
.enableLombok()
.formatFileName("%s")
.mapperBuilder()
.enableBaseResultMap()
.formatMapperFileName("%sMapper")
.formatXmlFileName("%sMapper")
.serviceBuilder()
.formatServiceFileName("%sService")
.formatServiceImplFileName("%sServiceImpl")
.controllerBuilder()
.enableRestStyle()
.formatFileName("%sController");
//当表名中带*号时可以启用通配符模式
if (tableNames.length == 1 && tableNames[0].contains("*")) {
String[] likeStr = tableNames[0].split("_");
String likePrefix = likeStr[0] + "_";
builder.likeTable(new LikeTable(likePrefix));
} else {
builder.addInclude(tableNames);
}
return builder.build();
}
//初始化自定义配置
private static InjectionConfig initInjectionConfig(String projectPath, String moduleName) {
// 自定义配置
return new InjectionConfig.Builder().build();
}
}
- 初始化数据源的配置文件为generator.properties:
dataSource.url=jdbc:mysql://localhost:3306/mall_tiny?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai
dataSource.driverName=com.mysql.jdbc.Driver
dataSource.username=root
dataSource.password=123456
package.base=org.example.module
- 工具自带的controller层没有内容,所以添加一个模板文件controller.java.vm:
package ${package.Controller};
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.example.common.api.CommonResult;
import ${package.Entity}.${table.entityName};
import ${package.Service}.${table.serviceName};
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
/**
* <p>
* $!{table.comment} 前端控制器
* </p>
*
* @author ${author}
* @since ${date}
*/
@RestController
@RequestMapping("${package.ModuleName}/${table.entityPath}")
@Api(tags = "${table.entityPath}")
public class ${table.controllerName} {
@Autowired
private ${table.serviceName} ${table.entityPath}Service;
//列表 TODO
@RequestMapping("/list")
@ApiOperation(value = "列表")
public CommonResult list(@RequestParam Map<String, Object> params){
List<${table.entityName}> list = ${table.entityPath}Service.list();
return CommonResult.success(list, "list");
}
//信息
@RequestMapping("/info/{id}")
@ApiOperation(value = "信息")
public CommonResult info(@PathVariable("id") Long id){
${table.entityName} ${table.entityPath} = ${table.entityPath}Service.getById(id);
return CommonResult.success(${table.entityPath}, "${table.entityPath}");
}
//保存
@RequestMapping("/save")
@ApiOperation(value = "保存")
public CommonResult save(@RequestBody ${table.entityName} ${table.entityPath}){
${table.entityPath}Service.save(${table.entityPath});
return CommonResult.success(1);
}
//修改
@RequestMapping("/update")
@ApiOperation(value = "修改")
public CommonResult update(@RequestBody ${table.entityName} ${table.entityPath}){
${table.entityPath}Service.updateById(${table.entityPath});
return CommonResult.success(1);
}
//删除
@RequestMapping("/delete")
@ApiOperation(value = "删除")
public CommonResult delete(@RequestBody Long[] ids){
${table.entityPath}Service.removeByIds(Arrays.asList(ids));
return CommonResult.success(1);
}
}
模板文件中的变量:
${package.Controller} org.example.module.aaa.controller
${package.Service} org.example.module.aaa.service
${package.ModuleName} aaa
${table.controllerName} SysAdminController
${table.serviceName} SysAdminService
${table.entityPath} sysAdmin
$!{table.comment} 后台用户表
${controllerMappingHyphen} sys-admin
${controllerMappingHyphenStyle} false
${restControllerStyle} true
${superControllerClassPackage} ${superControllerClassPackage}
${author} java
${date} 2022-09-15
#参考配置文件中的变量
com\baomidou\mybatis-plus-generator\3.5.1\mybatis-plus-generator-3.5.1.jar!\templates\controller.java.vm
- 另外需要创建基础工具类:统一返回值
CommonResult:
package org.example.common.api;
/**
* 统一返回对象
*/
public class CommonResult<T> {
private long code;
private String message;
private T data;
protected CommonResult() {
}
protected CommonResult(long code, String message, T data) {
this.code = code;
this.message = message;
this.data = data;
}
/**
* 成功返回结果
*/
public static <T> CommonResult<T> success(T data) {
return new CommonResult<T>(ResultCode.SUCCESS.getCode(), ResultCode.SUCCESS.getMessage(), data);
}
/**
* 成功返回结果
*/
public static <T> CommonResult<T> success(T data, String message) {
return new CommonResult<T>(ResultCode.SUCCESS.getCode(), message, data);
}
/**
* 失败返回结果
*/
public static <T> CommonResult<T> failed(IErrorCode errorCode) {
return new CommonResult<T>(errorCode.getCode(), errorCode.getMessage(), null);
}
/**
* 失败返回结果
*/
public static <T> CommonResult<T> failed(IErrorCode errorCode,String message) {
return new CommonResult<T>(errorCode.getCode(), message, null);
}
/**
* 失败返回结果
*/
public static <T> CommonResult<T> failed(String message) {
return new CommonResult<T>(ResultCode.FAILED.getCode(), message, null);
}
/**
* 失败返回结果
*/
public static <T> CommonResult<T> failed() {
return failed(ResultCode.FAILED);
}
/**
* 参数验证失败返回结果
*/
public static <T> CommonResult<T> validateFailed() {
return failed(ResultCode.VALIDATE_FAILED);
}
/**
* 参数验证失败返回结果
*/
public static <T> CommonResult<T> validateFailed(String message) {
return new CommonResult<T>(ResultCode.VALIDATE_FAILED.getCode(), message, null);
}
/**
* 未登录返回结果
*/
public static <T> CommonResult<T> unauthorized(T data) {
return new CommonResult<T>(ResultCode.UNAUTHORIZED.getCode(), ResultCode.UNAUTHORIZED.getMessage(), data);
}
/**
* 未授权返回结果
*/
public static <T> CommonResult<T> forbidden(T data) {
return new CommonResult<T>(ResultCode.FORBIDDEN.getCode(), ResultCode.FORBIDDEN.getMessage(), data);
}
public long getCode() {
return code;
}
public void setCode(long code) {
this.code = code;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
}
ResultCode:
package org.example.common.api;
/**
* 枚举了一些常用API操作码
*/
public enum ResultCode implements IErrorCode {
SUCCESS(200, "操作成功"),
FAILED(500, "操作失败"),
VALIDATE_FAILED(404, "参数检验失败"),
UNAUTHORIZED(401, "暂未登录或token已经过期"),
FORBIDDEN(403, "没有相关权限");
private long code;
private String message;
private ResultCode(long code, String message) {
this.code = code;
this.message = message;
}
public long getCode() {
return code;
}
public String getMessage() {
return message;
}
}
IErrorCode:
package org.example.common.api;
/**
* 封装API的错误码
*/
public interface IErrorCode {
long getCode();
String getMessage();
}
- 运行文件:MyBatisPlusGenerator,自动生成目录module.xxx(模块)相关代码,其他模块也类似操作,分别输入:sys(模块名)、sys_*(表)
- MyBatis-Plus提供的增强功能相当强大,单表查询几乎不用手写SQL,直接使用ServiceImpl和BaseMapper中提供的方法即可。
2.添加基础配置
2.1 添加配置文件application.yml
- 主配置文件:
server:
port: 8080
spring:
application:
name: base-sys
profiles:
active: dev
mybatis-plus:
mapper-locations: classpath:/mapper/**/*.xml
global-config:
db-config:
id-type: auto
configuration:
auto-mapping-behavior: partial
map-underscore-to-camel-case: true
- 配置了多环境,开发环境为application-dev.yml:
spring:
datasource:
url: jdbc:mysql://localhost:3306/mall_tiny?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai&useSSL=false
username: root
password: 123456
redis:
host: 101.43.52.64
database: 1
port: 6379
password: 123456
timeout: 3000ms
logging:
level:
root: info
org.example: debug
2.2 配置MybatisPlus
package org.example.config;
import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.transaction.annotation.EnableTransactionManagement;
/**
* MyBatis配置类
*/
@Configuration
@EnableTransactionManagement
@MapperScan({"org.example.modules.*.mapper"})
public class MyBatisConfig {
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
return interceptor;
}
}
2.3 配置Swagger
- 自定义配置属性:
package org.example.common.config.property;
import lombok.Builder;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
* Swagger自定义配置
*/
@Data
@EqualsAndHashCode(callSuper = false)
@Builder
public class SwaggerProperties {
//API文档生成基础路径
private String apiBasePackage;
//是否要启用登录认证
private boolean enableSecurity;
//文档标题
private String title;
//文档描述
private String description;
//文档版本
private String version;
//文档联系人姓名
private String contactName;
//文档联系人网址
private String contactUrl;
//文档联系人邮箱
private String contactEmail;
}
- 创建一个抽象基础类,定义基础配置:
package org.example.common.config.base;
import org.example.common.config.property.SwaggerProperties;
import org.springframework.context.annotation.Bean;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.*;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spi.service.contexts.SecurityContext;
import springfox.documentation.spring.web.plugins.Docket;
import java.util.ArrayList;
import java.util.List;
/**
* Swagger基础配置
*/
public abstract class BaseSwaggerConfig {
@Bean
public Docket createRestApi() {
SwaggerProperties swaggerProperties = swaggerProperties();
Docket docket = new Docket(DocumentationType.SWAGGER_2)
.apiInfo(apiInfo(swaggerProperties))
.select()
.apis(RequestHandlerSelectors.basePackage(swaggerProperties.getApiBasePackage()))
.paths(PathSelectors.any())
.build();
if (swaggerProperties.isEnableSecurity()) {
docket.securitySchemes(securitySchemes()).securityContexts(securityContexts());
}
return docket;
}
private ApiInfo apiInfo(SwaggerProperties swaggerProperties) {
return new ApiInfoBuilder()
.title(swaggerProperties.getTitle())
.description(swaggerProperties.getDescription())
.contact(new Contact(swaggerProperties.getContactName(), swaggerProperties.getContactUrl(), swaggerProperties.getContactEmail()))
.version(swaggerProperties.getVersion())
.build();
}
private List<SecurityScheme> securitySchemes() {
//设置请求头信息
List<SecurityScheme> result = new ArrayList<>();
ApiKey apiKey = new ApiKey("Authorization", "Authorization", "header");
result.add(apiKey);
return result;
}
private List<SecurityContext> securityContexts() {
//设置需要登录认证的路径
List<SecurityContext> result = new ArrayList<>();
result.add(getContextByPath("/*/.*"));
return result;
}
private SecurityContext getContextByPath(String pathRegex) {
return SecurityContext.builder()
.securityReferences(defaultAuth())
.forPaths(PathSelectors.regex(pathRegex))
.build();
}
private List<SecurityReference> defaultAuth() {
List<SecurityReference> result = new ArrayList<>();
AuthorizationScope authorizationScope = new AuthorizationScope("global", "accessEverything");
AuthorizationScope[] authorizationScopes = new AuthorizationScope[1];
authorizationScopes[0] = authorizationScope;
result.add(new SecurityReference("Authorization", authorizationScopes));
return result;
}
/**
* 自定义Swagger配置
*/
public abstract SwaggerProperties swaggerProperties();
}
- Swagger API文档相关配置:先不启用安全
package org.example.config;
import org.example.common.config.base.BaseSwaggerConfig;
import org.example.common.config.property.SwaggerProperties;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.util.ReflectionUtils;
import org.springframework.web.servlet.mvc.method.RequestMappingInfoHandlerMapping;
import springfox.documentation.spring.web.plugins.WebFluxRequestHandlerProvider;
import springfox.documentation.spring.web.plugins.WebMvcRequestHandlerProvider;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
import java.lang.reflect.Field;
import java.util.List;
import java.util.stream.Collectors;
/**
* Swagger API文档相关配置
*/
@Configuration
@EnableSwagger2
public class SwaggerConfig extends BaseSwaggerConfig {
@Override
public SwaggerProperties swaggerProperties() {
return SwaggerProperties.builder()
.apiBasePackage("org.example.module.sys.controller")
.title("base-sys")
.description("base-sys相关接口文档")
.contactName("java")
.version("1.0")
.enableSecurity(false)
.build();
}
@Bean
public static BeanPostProcessor springfoxHandlerProviderBeanPostProcessor() {
return new BeanPostProcessor() {
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if (bean instanceof WebMvcRequestHandlerProvider || bean instanceof WebFluxRequestHandlerProvider) {
customizeSpringfoxHandlerMappings(getHandlerMappings(bean));
}
return bean;
}
private <T extends RequestMappingInfoHandlerMapping> void customizeSpringfoxHandlerMappings(List<T> mappings) {
List<T> copy = mappings.stream()
.filter(mapping -> mapping.getPatternParser() == null)
.collect(Collectors.toList());
mappings.clear();
mappings.addAll(copy);
}
@SuppressWarnings("unchecked")
private List<RequestMappingInfoHandlerMapping> getHandlerMappings(Object bean) {
try {
Field field = ReflectionUtils.findField(bean.getClass(), "handlerMappings");
field.setAccessible(true);
return (List<RequestMappingInfoHandlerMapping>) field.get(bean);
} catch (IllegalArgumentException | IllegalAccessException e) {
throw new IllegalStateException(e);
}
}
};
}
}
2.4 配置Redis
- 创建工具类接口
package org.example.common.config.service;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* redis操作Service
*/
public interface RedisService {
/**
* 保存属性
*/
void set(String key, Object value, long time);
/**
* 保存属性
*/
void set(String key, Object value);
/**
* 获取属性
*/
Object get(String key);
/**
* 删除属性
*/
Boolean del(String key);
/**
* 批量删除属性
*/
Long del(List<String> keys);
/**
* 设置过期时间
*/
Boolean expire(String key, long time);
/**
* 获取过期时间
*/
Long getExpire(String key);
/**
* 判断是否有该属性
*/
Boolean hasKey(String key);
/**
* 按delta递增
*/
Long incr(String key, long delta);
/**
* 按delta递减
*/
Long decr(String key, long delta);
/**
* 获取Hash结构中的属性
*/
Object hGet(String key, String hashKey);
/**
* 向Hash结构中放入一个属性
*/
Boolean hSet(String key, String hashKey, Object value, long time);
/**
* 向Hash结构中放入一个属性
*/
void hSet(String key, String hashKey, Object value);
/**
* 直接获取整个Hash结构
*/
Map<Object, Object> hGetAll(String key);
/**
* 直接设置整个Hash结构
*/
Boolean hSetAll(String key, Map<String, Object> map, long time);
/**
* 直接设置整个Hash结构
*/
void hSetAll(String key, Map<String, ?> map);
/**
* 删除Hash结构中的属性
*/
void hDel(String key, Object... hashKey);
/**
* 判断Hash结构中是否有该属性
*/
Boolean hHasKey(String key, String hashKey);
/**
* Hash结构中属性递增
*/
Long hIncr(String key, String hashKey, Long delta);
/**
* Hash结构中属性递减
*/
Long hDecr(String key, String hashKey, Long delta);
/**
* 获取Set结构
*/
Set<Object> sMembers(String key);
/**
* 向Set结构中添加属性
*/
Long sAdd(String key, Object... values);
/**
* 向Set结构中添加属性
*/
Long sAdd(String key, long time, Object... values);
/**
* 是否为Set中的属性
*/
Boolean sIsMember(String key, Object value);
/**
* 获取Set结构的长度
*/
Long sSize(String key);
/**
* 删除Set结构中的属性
*/
Long sRemove(String key, Object... values);
/**
* 获取List结构中的属性
*/
List<Object> lRange(String key, long start, long end);
/**
* 获取List结构的长度
*/
Long lSize(String key);
/**
* 根据索引获取List中的属性
*/
Object lIndex(String key, long index);
/**
* 向List结构中添加属性
*/
Long lPush(String key, Object value);
/**
* 向List结构中添加属性
*/
Long lPush(String key, Object value, long time);
/**
* 向List结构中批量添加属性
*/
Long lPushAll(String key, Object... values);
/**
* 向List结构中批量添加属性
*/
Long lPushAll(String key, Long time, Object... values);
/**
* 从List结构中移除属性
*/
Long lRemove(String key, long count, Object value);
}
- 实现类
package org.example.common.config.service.impl;
import org.example.common.config.service.RedisService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;
/**
* redis操作实现类
*/
public class RedisServiceImpl implements RedisService {
@Autowired
private RedisTemplate<String, Object> redisTemplate;
@Override
public void set(String key, Object value, long time) {
redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS);
}
@Override
public void set(String key, Object value) {
redisTemplate.opsForValue().set(key, value);
}
@Override
public Object get(String key) {
return redisTemplate.opsForValue().get(key);
}
@Override
public Boolean del(String key) {
return redisTemplate.delete(key);
}
@Override
public Long del(List<String> keys) {
return redisTemplate.delete(keys);
}
@Override
public Boolean expire(String key, long time) {
return redisTemplate.expire(key, time, TimeUnit.SECONDS);
}
@Override
public Long getExpire(String key) {
return redisTemplate.getExpire(key, TimeUnit.SECONDS);
}
@Override
public Boolean hasKey(String key) {
return redisTemplate.hasKey(key);
}
@Override
public Long incr(String key, long delta) {
return redisTemplate.opsForValue().increment(key, delta);
}
@Override
public Long decr(String key, long delta) {
return redisTemplate.opsForValue().increment(key, -delta);
}
@Override
public Object hGet(String key, String hashKey) {
return redisTemplate.opsForHash().get(key, hashKey);
}
@Override
public Boolean hSet(String key, String hashKey, Object value, long time) {
redisTemplate.opsForHash().put(key, hashKey, value);
return expire(key, time);
}
@Override
public void hSet(String key, String hashKey, Object value) {
redisTemplate.opsForHash().put(key, hashKey, value);
}
@Override
public Map<Object, Object> hGetAll(String key) {
return redisTemplate.opsForHash().entries(key);
}
@Override
public Boolean hSetAll(String key, Map<String, Object> map, long time) {
redisTemplate.opsForHash().putAll(key, map);
return expire(key, time);
}
@Override
public void hSetAll(String key, Map<String, ?> map) {
redisTemplate.opsForHash().putAll(key, map);
}
@Override
public void hDel(String key, Object... hashKey) {
redisTemplate.opsForHash().delete(key, hashKey);
}
@Override
public Boolean hHasKey(String key, String hashKey) {
return redisTemplate.opsForHash().hasKey(key, hashKey);
}
@Override
public Long hIncr(String key, String hashKey, Long delta) {
return redisTemplate.opsForHash().increment(key, hashKey, delta);
}
@Override
public Long hDecr(String key, String hashKey, Long delta) {
return redisTemplate.opsForHash().increment(key, hashKey, -delta);
}
@Override
public Set<Object> sMembers(String key) {
return redisTemplate.opsForSet().members(key);
}
@Override
public Long sAdd(String key, Object... values) {
return redisTemplate.opsForSet().add(key, values);
}
@Override
public Long sAdd(String key, long time, Object... values) {
Long count = redisTemplate.opsForSet().add(key, values);
expire(key, time);
return count;
}
@Override
public Boolean sIsMember(String key, Object value) {
return redisTemplate.opsForSet().isMember(key, value);
}
@Override
public Long sSize(String key) {
return redisTemplate.opsForSet().size(key);
}
@Override
public Long sRemove(String key, Object... values) {
return redisTemplate.opsForSet().remove(key, values);
}
@Override
public List<Object> lRange(String key, long start, long end) {
return redisTemplate.opsForList().range(key, start, end);
}
@Override
public Long lSize(String key) {
return redisTemplate.opsForList().size(key);
}
@Override
public Object lIndex(String key, long index) {
return redisTemplate.opsForList().index(key, index);
}
@Override
public Long lPush(String key, Object value) {
return redisTemplate.opsForList().rightPush(key, value);
}
@Override
public Long lPush(String key, Object value, long time) {
Long index = redisTemplate.opsForList().rightPush(key, value);
expire(key, time);
return index;
}
@Override
public Long lPushAll(String key, Object... values) {
return redisTemplate.opsForList().rightPushAll(key, values);
}
@Override
public Long lPushAll(String key, Long time, Object... values) {
Long count = redisTemplate.opsForList().rightPushAll(key, values);
expire(key, time);
return count;
}
@Override
public Long lRemove(String key, long count, Object value) {
return redisTemplate.opsForList().remove(key, count, value);
}
}
- 创建一个抽象基础类,实现基础配置
package org.example.common.config.base;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.jsontype.impl.LaissezFaireSubTypeValidator;
import org.example.common.config.service.RedisService;
import org.example.common.config.service.impl.RedisServiceImpl;
import org.springframework.context.annotation.Bean;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.cache.RedisCacheWriter;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializationContext;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import java.time.Duration;
/**
* Redis基础配置
*/
public class BaseRedisConfig {
@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
RedisSerializer<Object> serializer = redisSerializer();
RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
redisTemplate.setConnectionFactory(redisConnectionFactory);
redisTemplate.setKeySerializer(new StringRedisSerializer());
redisTemplate.setValueSerializer(serializer);
redisTemplate.setHashKeySerializer(new StringRedisSerializer());
redisTemplate.setHashValueSerializer(serializer);
redisTemplate.afterPropertiesSet();
return redisTemplate;
}
@Bean
public RedisSerializer<Object> redisSerializer() {
//创建JSON序列化器
Jackson2JsonRedisSerializer<Object> serializer = new Jackson2JsonRedisSerializer<>(Object.class);
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
//必须设置,否则无法将JSON转化为对象,会转化成Map类型
objectMapper.activateDefaultTyping(LaissezFaireSubTypeValidator.instance,ObjectMapper.DefaultTyping.NON_FINAL);
serializer.setObjectMapper(objectMapper);
return serializer;
}
@Bean
public RedisCacheManager redisCacheManager(RedisConnectionFactory redisConnectionFactory) {
RedisCacheWriter redisCacheWriter = RedisCacheWriter.nonLockingRedisCacheWriter(redisConnectionFactory);
//设置Redis缓存有效期为1天
RedisCacheConfiguration redisCacheConfiguration = RedisCacheConfiguration.defaultCacheConfig()
.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(redisSerializer())).entryTtl(Duration.ofDays(1));
return new RedisCacheManager(redisCacheWriter, redisCacheConfiguration);
}
@Bean
public RedisService redisService(){
return new RedisServiceImpl();
}
}
- Redis配置类
package org.example.config;
import org.example.common.config.base.BaseRedisConfig;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Configuration;
/**
* Redis配置类
*/
@EnableCaching
@Configuration
public class RedisConfig extends BaseRedisConfig {
}
2.5 全局跨域配置
package org.example.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;
/**
* 全局跨域配置
*/
@Configuration
public class GlobalCorsConfig {
/**
* 允许跨域调用的过滤器
*/
@Bean
public CorsFilter corsFilter() {
CorsConfiguration config = new CorsConfiguration();
//允许所有域名进行跨域调用
config.addAllowedOriginPattern("*");
//该用法在SpringBoot 2.7.0中已不再支持
//config.addAllowedOrigin("*");
//允许跨越发送cookie
config.setAllowCredentials(true);
//放行全部原始头信息
config.addAllowedHeader("*");
//允许所有请求方法跨域调用
config.addAllowedMethod("*");
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", config);
return new CorsFilter(source);
}
}
2.6 统一异常处理
- 自定义API异常
package org.example.common.exception;
import org.example.common.api.IErrorCode;
/**
* 自定义API异常
*/
public class ApiException extends RuntimeException {
private IErrorCode errorCode;
public ApiException(IErrorCode errorCode) {
super(errorCode.getMessage());
this.errorCode = errorCode;
}
public ApiException(String message) {
super(message);
}
public ApiException(Throwable cause) {
super(cause);
}
public ApiException(String message, Throwable cause) {
super(message, cause);
}
public IErrorCode getErrorCode() {
return errorCode;
}
}
- 全局异常处理
package org.example.common.exception;
import org.example.common.api.CommonResult;
import org.springframework.validation.BindException;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
/**
* 全局异常处理
*/
@ControllerAdvice
public class GlobalExceptionHandler {
@ResponseBody
@ExceptionHandler(value = ApiException.class)
public CommonResult handle(ApiException e) {
if (e.getErrorCode() != null) {
return CommonResult.failed(e.getErrorCode());
}
return CommonResult.failed(e.getMessage());
}
@ResponseBody
@ExceptionHandler(value = MethodArgumentNotValidException.class)
public CommonResult handleValidException(MethodArgumentNotValidException e) {
BindingResult bindingResult = e.getBindingResult();
String message = null;
if (bindingResult.hasErrors()) {
FieldError fieldError = bindingResult.getFieldError();
if (fieldError != null) {
message = fieldError.getField() + fieldError.getDefaultMessage();
}
}
return CommonResult.validateFailed(message);
}
@ResponseBody
@ExceptionHandler(value = BindException.class)
public CommonResult handleValidException(BindException e) {
BindingResult bindingResult = e.getBindingResult();
String message = null;
if (bindingResult.hasErrors()) {
FieldError fieldError = bindingResult.getFieldError();
if (fieldError != null) {
message = fieldError.getField() + fieldError.getDefaultMessage();
}
}
return CommonResult.validateFailed(message);
}
}
2.7 启动项目,验证
- 启动项目,可以正常启动,访问:http://localhost:8080/swagger-ui/ 正常看到接口;