前言
到了這裏過後,我們劇本的架子已經基本搭起來了。我們可以開始進行大規模的表演了。在開始表演之前,我們要在採購一個道具,這個道具就是代碼生成。我們很多的領域模型、vo、dto、entity等實體以及我們的dao層、service層、controller層、甚至我們的前端代碼都能使用代碼生成器進行生成。這樣會節約我們很多的時間,讓我們專注於業務上,不必在從數據庫或者其他實體中來回的進行ctrl+c,ctrl+v。
首先在我們的IDEA中安裝easyCode的插件,但是安裝之前有個小坑,因爲需要用到IDEA的“DataBase”,所以社區版的不能用這玩意,在這裏悄悄咪咪的告訴各位一款PJ神器,專注PJ100年的那種。反正我身邊的朋友用了都說好,當然也不知道啥時候會被幹掉。
JetBrains全家桶:https://shimo.im/docs/WY3hd8Jt8KHgvVty/read
介紹
EasyCode是基於IntelliJ IDEA開發的代碼生成插件,支持自定義任意模板(Java,html,js,xml)。只要是與數據庫相關的代碼都可以通過自定義模板來生成。支持數據庫類型與java類型映射關係配置。支持同時生成生成多張表的代碼。每張表有獨立的配置信息。完全的個性化定義,規則由你設置。
源碼倉庫:https://gitee.com/makejava/EasyCode
文檔:https://gitee.com/makejava/EasyCode/wikis/pages
貢獻者
安裝
easyCode插件的安裝,請選擇“數據海洋”
創建DataSource
填寫你的鏈接信息
記得第一次要注意驅動的問題,點擊Driver後面的鏈接可以配置驅動。
配置完成點擊一下Test Connection如果提示成功就可以點擊ok,來進行下面的配置了
添加數據類型
我們先來進行默認的生成測試,右鍵sys_role表,然後點擊“EasyCode --> Generate Code”
這個時候提示我們沒有tinyint的數據類型,我們點擊Yes去配置一下
將mysql數據庫的tinyint類型映射爲java的Integer類型
這個時候我們在繼續生成
看看生成的效果,紅色的部分都是生成的代碼
可以看到,生成的代碼有很多缺陷,我們的lombok並沒有用上,而且Mybatis-Plus也沒有用到,加上我們的頁面啊什麼的也沒有生成到。
那麼讓我們來定製一下生成的模版吧,在配置頁面
搜索easy Code,選擇Template Setting,配置我們的模版
這裏我就不詳細介紹easyCode裏面的標籤了,大家可以參照文檔來進行配置:https://gitee.com/makejava/EasyCode/wikis/pages
標籤的話參考Velocity模板引擎語法:https://www.cnblogs.com/yangzhinian/p/4885973.html
模版設置
修改作者
全局配置(Golbal Config)
init
##初始化區域
##去掉表的t_前綴
#if($tableInfo.obj.name.startsWith("自定義前綴_"))
$!tableInfo.setName($tool.getClassName($tableInfo.obj.name.substring(4)))
#end
## 定義版本號
#set($version = "1.0.0")
## 標記刪除字段
#set($delete = "is_deleted")
## 創建時間標識
#set($createTime = "create_time")
## 公共字段
#set($publicFelids = $tool.newHashSet(
"createTime",
"createUserId",
"modifyTime",
"modifyUserId",
"isDeleted",
"remark"
))
##實現動態排除列
#set($temp = $tool.newHashSet("testCreateTime", "otherColumn"))
#foreach($item in $temp)
#set($newList = $tool.newArrayList())
#foreach($column in $tableInfo.fullColumn)
#if($column.name!=$item)
##帶有反回值的方法調用時使用$tool.call來消除返回值
$tool.call($newList.add($column))
#end
#end
##重新保存
$tableInfo.setFullColumn($newList)
#end
##對importList進行篡改
#set($temp = $tool.newHashSet())
#foreach($column in $tableInfo.fullColumn)
#if(!$column.type.startsWith("java.lang."))
##帶有反回值的方法調用時使用$tool.call來消除返回值
$tool.call($temp.add($column.type))
#end
#end
##覆蓋
#set($importList = $temp)
define
##(Velocity宏定義)
##定義設置表名後綴的宏定義,調用方式:#setTableSuffix("Test")
#macro(setTableSuffix $suffix)
#set($tableName = $!tool.append($tableInfo.name, $suffix))
#end
##定義設置包名後綴的宏定義,調用方式:#setPackageSuffix("Test")
#macro(setPackageSuffix $suffix)
#if($suffix!="")package #end#if($tableInfo.savePackageName!="")$!{tableInfo.savePackageName}.#{end}$!suffix;
#end
##定義直接保存路徑與文件名簡化的宏定義,調用方式:#save("/entity", ".java")
#macro(save $path $fileName)
$!callback.setSavePath($tool.append($tableInfo.savePath, $path))
$!callback.setFileName($tool.append($tableInfo.name, $fileName))
#end
##定義表註釋的宏定義,調用方式:#tableComment("註釋信息")
#macro(tableComment $desc)
/**
* $!{tableInfo.comment}($!{tableInfo.name})$desc
*
* @author $!author
* @data $!time.currTime()
*/
#end
##定義GET,SET方法的宏定義,調用方式:#getSetMethod($column)
#macro(getSetMethod $column)
public $!{tool.getClsNameByFullName($column.type)} get$!{tool.firstUpperCase($column.name)}() {
return $!{column.name};
}
public void set$!{tool.firstUpperCase($column.name)}($!{tool.getClsNameByFullName($column.type)} $!{column.name}) {
this.$!{column.name} = $!{column.name};
}
#end
autoImport
##自動導入包(僅導入實體屬性需要的包,通常用於實體類)
#foreach($import in $importList)
import $!import;
#end
mybatisSupport
##針對Mybatis 進行支持,主要用於生成xml文件
#foreach($column in $tableInfo.fullColumn)
##儲存列類型
$tool.call($column.ext.put("sqlType", $tool.getField($column.obj.dataType, "typeName")))
#if($tool.newHashSet("java.lang.String").contains($column.type))
#set($jdbcType="VARCHAR")
#elseif($tool.newHashSet("java.lang.Boolean", "boolean").contains($column.type))
#set($jdbcType="BOOLEAN")
#elseif($tool.newHashSet("java.lang.Byte", "byte").contains($column.type))
#set($jdbcType="BYTE")
#elseif($tool.newHashSet("java.lang.Integer", "int", "java.lang.Short", "short").contains($column.type))
#set($jdbcType="INTEGER")
#elseif($tool.newHashSet("java.lang.Long", "long").contains($column.type))
#set($jdbcType="INTEGER")
#elseif($tool.newHashSet("java.lang.Float", "float", "java.lang.Double", "double").contains($column.type))
#set($jdbcType="NUMERIC")
#elseif($tool.newHashSet("java.util.Date", "java.sql.Timestamp", "java.time.Instant", "java.time.LocalDateTime", "java.time.OffsetDateTime", " java.time.ZonedDateTime").contains($column.type))
#set($jdbcType="TIMESTAMP")
#elseif($tool.newHashSet("java.sql.Date", "java.time.LocalDate").contains($column.type))
#set($jdbcType="TIMESTAMP")
#else
##其他類型
#set($jdbcType="OTHER")
#end
$tool.call($column.ext.put("jdbcType", $jdbcType))
#end
##定義宏,查詢所有列
#macro(allSqlColumn)#foreach($column in $tableInfo.fullColumn)$column.obj.name#if($velocityHasNext), #end#end#end
模版配置(Template Config)
entity.java
##引入宏定義
$!init
$!define
##定義初始變量
#set($tableName=$tool.append($tableInfo.name,"Entity"))
##設置回調
$!callback.setFileName($tool.append($tableName,".java"))
$!callback.setSavePath($tool.append($tableInfo.savePath,"/entity"))
##使用宏定義設置包後綴
#setPackageSuffix("entity")
##使用全局變量實現默認包導入
$!autoImport
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.hzw.code.common.constant.BaseEntity;
import io.swagger.annotations.ApiModelProperty;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
#tableComment("數據訪問類")
@Getter
@Setter
@ToString(callSuper = true)
@EqualsAndHashCode
@TableName("$!{tableInfo.obj.name}")
public class $!{tableName} extends BaseEntity{
/**
* 序列號
*/
private static final long serialVersionUID = $!tool.serial();
#if(!$tableInfo.pkColumn.isEmpty())
#set($pk = $tableInfo.pkColumn.get(0))
/**
* $!{pk.comment}
*/
@TableId
@ApiModelProperty(name = "$!{pk.name}", value = "$!{pk.comment}")
private $!{tool.getClsNameByFullName($pk.type)} $!{pk.name};
#end
#foreach($column in $tableInfo.otherColumn)
#set($have = false)
#foreach($felid in $publicFelids)
#if($column.name==$felid)
#set($have = true)
#break
#end
#end
#if(!$have)
/**
* $!{column.comment}
*/
#if(${column.comment})@ApiModelProperty(name = "$!{column.name}", value = "${column.comment}") #end
private $!{tool.getClsNameByFullName($column.type)} $!{column.name};
#end
#end
}
mapper.xml
##引入宏定義
$!init
$!define
##引入mybatis支持
$!mybatisSupport
##設置保存名稱與保存位置
$!callback.setFileName($tool.append($!{tableInfo.name}, "Mapper.xml"))
#set($tempIndex = $!tableInfo.savePackageName.lastIndexOf('.') + 1)
##set($mapppath=$tableInfo.savePackageName.substring($tempIndex))
$!callback.setSavePath($tool.append($modulePath, "/src/main/resources/mapper/"))
##拿到主鍵
#if(!$tableInfo.pkColumn.isEmpty())
#set($pk = $tableInfo.pkColumn.get(0))
#end
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="$!{tableInfo.savePackageName}.mapper.$!{tableInfo.name}Mapper">
<resultMap type="$!{tableInfo.savePackageName}.entity.$!{tableInfo.name}Entity" id="$!{tableInfo.name}Map">
#foreach($column in $tableInfo.fullColumn)
<result property="$!column.name" column="$!column.obj.name" jdbcType="$!column.ext.jdbcType"/>
#end
</resultMap>
<!--數據庫字段-->
<sql id="Column_List">
#allSqlColumn()
</sql>
<!--通過實體作爲篩選條件分頁查詢-->
<select id="page" resultType="$!{tableInfo.savePackageName}.dto.page.$!{tableInfo.name}PageDto">
SELECT
<include refid="Column_List"/>
FROM $!tableInfo.obj.name
<where>
${delete} = 0
#foreach($column in $tableInfo.fullColumn)
#if($!column.obj.name==$createTime)
<if test="query.startTime != null">
AND $!column.obj.name >= #{query.$!column.name, jdbcType=$!{column.ext.jdbcType}}
</if>
<if test="query.endTime != null">
AND $!column.obj.name <= #{query.$!column.name, jdbcType=$!{column.ext.jdbcType}}
</if>
#else
<if test="query.$!column.name != null#if($column.type.equals("java.lang.String")) and query.$!column.name != ''#end">
AND $!column.obj.name = #{query.$!column.name, jdbcType=$!{column.ext.jdbcType}}
</if>
#end
#end
</where>
</select>
<!--通過實體作爲篩選條件查詢-->
<select id="selectListByModel" resultType="$!{tableInfo.savePackageName}.dto.$!{tableInfo.name}Dto" parameterType="$!{tableInfo.savePackageName}.controller.args.$!{tableInfo.name}QueryArgs">
SELECT
<include refid="Column_List"/>
FROM $!tableInfo.obj.name
<where>
${delete} = 0
#foreach($column in $tableInfo.fullColumn)
<if test="$!column.name != null#if($column.type.equals("java.lang.String")) and $!column.name != ''#end">
AND $!column.obj.name = #{$!column.name, jdbcType=$!{column.ext.jdbcType}}
</if>
#end
</where>
</select>
<!-- 通過id邏輯刪除 -->
<update id="deleteById">
UPDATE $!tableInfo.obj.name
<set>
${delete} = 1,
#foreach($column in $tableInfo.fullColumn)
#if($column.obj.name.equals("index_help"))
$!column.obj.name = $!pk.obj.name,
#end
#end
</set>
WHERE $!pk.obj.name = #{$!pk.name, jdbcType=$!{pk.ext.jdbcType}}
</update>
</mapper>
mapper.java
##引入宏定義
$!init
$!define
##定義初始變量
#set($tableName=$tool.append($tableInfo.name,"Mapper"))
##設置回調
$!callback.setFileName($tool.append($tableName,".java"))
$!callback.setSavePath($tool.append($tableInfo.savePath,"/mapper"))
##拿到主鍵
#if(!$tableInfo.pkColumn.isEmpty())
#set($pk=$tableInfo.pkColumn.get(0))
#end
##使用宏定義設置包後綴
#setPackageSuffix("mapper")
##使用全局變量實現默認包導入
$!autoImport
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import $!{tableInfo.savePackageName}.controller.args.$!{tableInfo.name}PageArgs;
import $!{tableInfo.savePackageName}.controller.args.$!{tableInfo.name}QueryArgs;
import $!{tableInfo.savePackageName}.dto.$!{tableInfo.name}Dto;
import $!{tableInfo.savePackageName}.dto.page.$!{tableInfo.name}PageDto;
import $!{tableInfo.savePackageName}.entity.$!{tableInfo.name}Entity;
import org.apache.ibatis.annotations.Param;
import org.springframework.stereotype.Repository;
import java.util.List;
/**
* $!{tableInfo.comment}($!{tableInfo.name})持久層
*
* @author $!author
* @date $!time.currTime()
*/
@Repository
public interface $!{tableName} extends BaseMapper<$!{tableInfo.name}Entity>{
/**
* 分頁查詢
*
* @param args ${@link $!{tableInfo.name}PageArgs}
* @param page ${@link Page}
* @return IPage<$!{tableInfo.name}Dto> ${@link IPage<$!{tableInfo.name}Dto>}
* @author code generation
* @date $!time.currTime()
*/
IPage<$!{tableInfo.name}PageDto> page(Page page, @Param("query") $!{tableInfo.name}PageArgs args);
/**
* 條件查詢多條
*
* @param args ${@link $!{tableInfo.name}QueryArgs}
* @return List<$!{tableInfo.name}Dto> ${@link List<$!{tableInfo.name}Dto>}
* @author code generation
* @date $!time.currTime()
*/
List<$!{tableInfo.name}Dto> selectListByModel($!{tableInfo.name}QueryArgs args);
}
service.java
##引入宏定義
$!init
$!define
##定義初始變量
#set($tableName=$tool.append($tableInfo.name,"Service"))
##設置回調
$!callback.setFileName($tool.append($tableName,".java"))
$!callback.setSavePath($tool.append($tableInfo.savePath,"/service"))
##拿到主鍵
#if(!$tableInfo.pkColumn.isEmpty())
#set($pk=$tableInfo.pkColumn.get(0))
#end
##使用宏定義設置包後綴
#setPackageSuffix("service")
##使用全局變量實現默認包導入
$!autoImport
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.IService;
import $!{tableInfo.savePackageName}.controller.args.$!{tableInfo.name}Args;
import $!{tableInfo.savePackageName}.controller.args.$!{tableInfo.name}PageArgs;
import $!{tableInfo.savePackageName}.controller.args.$!{tableInfo.name}QueryArgs;
import $!{tableInfo.savePackageName}.dto.$!{tableInfo.name}Dto;
import $!{tableInfo.savePackageName}.dto.page.$!{tableInfo.name}PageDto;
import $!{tableInfo.savePackageName}.entity.$!{tableInfo.name}Entity;
import java.util.List;
/**
* $!{tableInfo.comment}($!{tableInfo.name})業務層接口
*
* @author $!author
* @date $!time.currTime()
*/
public interface $!{tableName} extends IService<$!{tableInfo.name}Entity> {
/**
* 保存
*
* @param args ${@link $!{tableInfo.name}Args}
* @throws RuntimeException ${@link RuntimeException}
* @author code generation
* @date $!time.currTime()
*/
void save($!{tableInfo.name}Args args) throws RuntimeException;
/**
* 通過id更新
*
* @param args ${@link $!{tableInfo.name}Args}
* @throws RuntimeException ${@link RuntimeException}
* @author code generation
* @date $!time.currTime()
*/
void updateById($!{tableInfo.name}Args args) throws RuntimeException;
/**
* 分頁查詢
*
* @param args ${@link $!{tableInfo.name}PageArgs}
* @throws RuntimeException ${@link RuntimeException}
* @return IPage<$!{tableInfo.name}PageDto> ${@link IPage<$!{tableInfo.name}Dto>}
* @author code generation
* @date $!time.currTime()
*/
IPage<$!{tableInfo.name}PageDto> page($!{tableInfo.name}PageArgs args) throws RuntimeException;
/**
* 條件查詢多條
*
* @param args ${@link $!{tableInfo.name}QueryArgs}
* @throws RuntimeException ${@link RuntimeException}
* @return List<$!{tableInfo.name}Dto> ${@link List<$!{tableInfo.name}Dto>}
* @author code generation
* @date $!time.currTime()
*/
List<$!{tableInfo.name}Dto> selectListByModel($!{tableInfo.name}QueryArgs args) throws RuntimeException;
/**
* 通過id查詢詳情
*
* @param id ${@link String}
* @throws RuntimeException ${@link RuntimeException}
* @return $!{tableInfo.name}Dto ${@link $!{tableInfo.name}Dto}
* @author code generation
* @date $!time.currTime()
*/
$!{tableInfo.name}Dto getById(String id) throws RuntimeException;
}
serviceImpl.java
##引入宏定義
$!init
$!define
##定義初始變量
#set($tableName=$tool.append($tableInfo.name,"ServiceImpl"))
##設置回調
$!callback.setFileName($tool.append($tableName,".java"))
$!callback.setSavePath($tool.append($tableInfo.savePath,"/service/impl"))
##拿到主鍵
#if(!$tableInfo.pkColumn.isEmpty())
#set($pk=$tableInfo.pkColumn.get(0))
#end
##使用宏定義設置包後綴
#setPackageSuffix("service.impl")
##使用全局變量實現默認包導入
$!autoImport
import $!{tableInfo.savePackageName}.controller.args.$!{tableInfo.name}Args;
import $!{tableInfo.savePackageName}.controller.args.$!{tableInfo.name}PageArgs;
import $!{tableInfo.savePackageName}.controller.args.$!{tableInfo.name}QueryArgs;
import $!{tableInfo.savePackageName}.dto.$!{tableInfo.name}Dto;
import $!{tableInfo.savePackageName}.dto.page.$!{tableInfo.name}PageDto;
import $!{tableInfo.savePackageName}.entity.$!{tableInfo.name}Entity;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import $!{tableInfo.savePackageName}.mapper.$!{tableInfo.name}Mapper;
import $!{tableInfo.savePackageName}.service.$!{tableInfo.name}Service;
import com.hzw.code.common.utils.ActionException;
import com.hzw.code.common.utils.ResultCodeEnum;
import lombok.extern.slf4j.Slf4j;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.beans.BeanUtils;
import java.util.List;
import org.springframework.transaction.annotation.Transactional;
/**
* $!{tableInfo.comment}($!{tableInfo.name})業務層實現
*
* @author $!author
* @date $!time.currTime()
*/
@Slf4j
@Service
@RequiredArgsConstructor
@Transactional
public class $!{tableName} extends ServiceImpl<$!{tableInfo.name}Mapper, $!{tableInfo.name}Entity> implements $!{tableInfo.name}Service {
private final $!{tableInfo.name}Mapper mapper;
@Override
public void save($!{tableInfo.name}Args args) throws RuntimeException {
$!{tableInfo.name}Entity entity = new $!{tableInfo.name}Entity();
BeanUtils.copyProperties(args, entity);
boolean result = super.save(entity);
if (!result) {
throw new ActionException(ResultCodeEnum.DATABASE_INSERT_ERROR);
}
}
@Override
public void updateById($!{tableInfo.name}Args args) throws RuntimeException {
// 查詢數據是否存在
this.getById(args.get$tool.firstUpperCase(${pk.name})());
// 更新數據
$!{tableInfo.name}Entity entity = new $!{tableInfo.name}Entity();
BeanUtils.copyProperties(args, entity);
boolean result = super.updateById(entity);
if (!result) {
throw new ActionException(ResultCodeEnum.DATABASE_UPDATE_ERROR);
}
}
@Override
public List<$!{tableInfo.name}Dto> selectListByModel($!{tableInfo.name}QueryArgs args) throws RuntimeException {
List<$!{tableInfo.name}Dto> list = mapper.selectListByModel(args);
if (list == null || list.isEmpty()) {
throw new ActionException(ResultCodeEnum.DATABASE_NODATA);
}
return list;
}
@Override
public IPage<$!{tableInfo.name}PageDto> page($!{tableInfo.name}PageArgs args) throws RuntimeException {
return mapper.page(args.getQueryPage(), args);
}
@Override
public $!{tableInfo.name}Dto getById(String id) throws RuntimeException {
$!{tableInfo.name}Entity byId = super.getById(id);
if (byId == null) {
throw new ActionException(ResultCodeEnum.DATABASE_NODATA);
}
$!{tableInfo.name}Dto dto = new $!{tableInfo.name}Dto();
BeanUtils.copyProperties(byId, dto);
return dto;
}
}
RestfulController.java
##引入宏定義
$!init
$!define
##定義初始變量
#set($tableName=$tool.append($tableInfo.name,"Controller"))
##設置回調
$!callback.setFileName($tool.append($tableName,".java"))
$!callback.setSavePath($tool.append($tableInfo.savePath,"/controller"))
##拿到主鍵
#if(!$tableInfo.pkColumn.isEmpty())
#set($pk=$tableInfo.pkColumn.get(0))
#end
##使用宏定義設置包後綴
#setPackageSuffix("controller")
##使用全局變量實現默認包導入
$!autoImport
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.hzw.code.common.constant.SuperController;
import com.hzw.code.common.constant.BaseConstant;
import com.hzw.code.common.utils.ActionException;
import com.hzw.code.common.utils.ActionResult;
import com.hzw.code.common.validation.group.Insert;
import com.hzw.code.common.validation.group.Update;
import lombok.RequiredArgsConstructor;
import $!{tableInfo.savePackageName}.controller.args.$!{tableInfo.name}Args;
import $!{tableInfo.savePackageName}.controller.args.$!{tableInfo.name}PageArgs;
import $!{tableInfo.savePackageName}.controller.args.$!{tableInfo.name}QueryArgs;
import $!{tableInfo.savePackageName}.dto.$!{tableInfo.name}Dto;
import $!{tableInfo.savePackageName}.dto.page.$!{tableInfo.name}PageDto;
import $!{tableInfo.savePackageName}.service.$!{tableInfo.name}Service;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.MediaType;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.validation.constraints.NotBlank;
import java.util.List;
import org.springframework.web.bind.annotation.*;
## 獲取主鍵
#if(!$tableInfo.pkColumn.isEmpty())
#set($pk = $tableInfo.pkColumn.get(0))
#end
/**
* $!{tableInfo.comment}($!{tableInfo.name})控制層
*
* @author $!author
* @date $!time.currTime()
*/
@Slf4j
@Validated
@RestController
@RequiredArgsConstructor
@Api(tags = "$!{tableInfo.name}", value = "$!{tableInfo.name}Api", description = "$!{tableInfo.name}Api接口相關")
@RequestMapping(value = BaseConstant.URI_DEPLOY_PREFIX + "/$tool.firstLowerCase($!{tableInfo.name})s", produces = MediaType.APPLICATION_JSON_VALUE)
public class $!{tableName} extends SuperController{
private final $!{tableInfo.name}Service service;
@ApiOperation(value = "添加(${version})", notes = "添加$!{tableInfo.comment}")
@PreAuthorize("hasAuthority('ROLE_ADMIN')")
@PostMapping
public ActionResult<String> insert(@RequestBody @Validated(Insert.class) $!{tableInfo.name}Args args) throws ActionException {
service.save(args);
return successMsg("添加成功");
}
@ApiOperation(value = "通過${pk.comment}修改(${version})", notes = "修改$!{tableInfo.comment}")
@PreAuthorize("hasAuthority('ROLE_ADMIN')")
@PutMapping
public ActionResult<Object> update(@RequestBody @Validated(Update.class) $!{tableInfo.name}Args args) throws ActionException {
service.updateById(args);
return successMsg("修改成功");
}
@ApiOperation(value = "邏輯刪除(${version})", notes = "刪除$!{tableInfo.comment}")
@ApiImplicitParam(paramType = "path", value = "${pk.comment}", name = "${pk.name}", required = true)
@PreAuthorize("hasAuthority('ROLE_ADMIN')")
@DeleteMapping(value = "/{${pk.name}}")
public ActionResult<String> delete(@PathVariable @NotBlank(message = "${pk.comment}不能爲空") String ${pk.name}) throws ActionException {
service.removeById(${pk.name});
return successMsg("刪除成功");
}
@ApiOperation(value = "通過${pk.comment}查詢詳情(${version})", notes = "查詢$!{tableInfo.comment}詳情")
@ApiImplicitParam(paramType = "path", value = "${pk.comment}", name = "${pk.name}", required = true)
@PreAuthorize("hasAuthority('ROLE_ADMIN')")
@GetMapping(value = "/{${pk.name}}")
public ActionResult<$!{tableInfo.name}Dto> getById(@PathVariable @NotBlank(message = "${pk.comment}不能爲空") String ${pk.name}) throws ActionException {
return successData(service.getById(${pk.name}));
}
@ApiOperation(value = "通過條件查詢多條數據(${version})", notes = "通過條件查詢$!{tableInfo.comment}")
@PreAuthorize("hasAuthority('ROLE_ADMIN')")
@GetMapping(value = "/list")
public ActionResult<List<$!{tableInfo.name}Dto>> getList($!{tableInfo.name}QueryArgs args) throws ActionException {
return successData(service.selectListByModel(args));
}
@ApiOperation(value = "分頁查詢(${version})", notes = "分頁查詢$!{tableInfo.comment}")
@PreAuthorize("hasAuthority('ROLE_ADMIN')")
@GetMapping(value = "/page")
public ActionResult<IPage<$!{tableInfo.name}PageDto>> selectPage($!{tableInfo.name}PageArgs args) throws ActionException {
return successData(service.page(args));
}
}
insertOrUpdateArgs.java
##引入宏定義
$!init
$!define
##定義初始變量
#set($tableName=$tool.append($tableInfo.name,"Args"))
##設置回調
$!callback.setFileName($tool.append($tableName,".java"))
$!callback.setSavePath($tool.append($tableInfo.savePath,"/controller/args"))
##使用宏定義設置包後綴
#setPackageSuffix("controller.args")
##使用全局變量實現默認包導入
$!autoImport
import com.hzw.code.common.validation.group.Update;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import javax.validation.constraints.NotBlank;
import java.io.Serializable;
import java.util.Date;
#tableComment("Args")
@Getter
@Setter
@ToString
@EqualsAndHashCode
@ApiModel(value = "$!{tableInfo.comment}添加或修改Request", description = "$!{tableInfo.comment}添加或修改入參")
public class $!{tableName} implements Serializable {
private static final long serialVersionUID = $!tool.serial();
#if(!$tableInfo.pkColumn.isEmpty())
#set($pk = $tableInfo.pkColumn.get(0))
/**
* $!{pk.comment}
*/
@ApiModelProperty(name = "$!{pk.name}", value = "$!{pk.comment}")
@NotBlank(message = "$!{pk.comment}不能爲空", groups = Update.class)
private $!{tool.getClsNameByFullName($pk.type)} $!{pk.name};
#end
#foreach($column in $tableInfo.otherColumn)
/**
* $!{column.name}
*/
#if(${column.comment})@ApiModelProperty(name = "$!{column.name}", value = "${column.comment}" #if($!{tool.getClsNameByFullName($column.type)} == 'Integer') , example = "1" #end) #end
private $!{tool.getClsNameByFullName($column.type)} $!{column.name};
#end
}
pageArgs.java
##引入宏定義
$!init
$!define
##定義初始變量
#set($tableName=$tool.append($tableInfo.name,"PageArgs"))
##設置回調
$!callback.setFileName($tool.append($tableName,".java"))
$!callback.setSavePath($tool.append($tableInfo.savePath,"/controller/args"))
##使用宏定義設置包後綴
#setPackageSuffix("controller.args")
##使用全局變量實現默認包導入
$!autoImport
import com.hzw.code.common.constant.SuperPageArgs;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
#tableComment("PageArgs")
@Getter
@Setter
@ToString
@ApiModel(value = "$!{tableInfo.comment}分頁查詢Request", description = "$!{tableInfo.comment}分頁查詢入參")
public class $!{tableName} extends SuperPageArgs {
private static final long serialVersionUID = $!tool.serial();
#foreach($column in $tableInfo.fullColumn)
/**
* $!{column.name}
*/
#if(${column.comment})@ApiModelProperty(name = "$!{column.name}", value = "${column.comment}" #if($!{tool.getClsNameByFullName($column.type)} == 'Integer') , example = "1" #end) #end
private $!{tool.getClsNameByFullName($column.type)} $!{column.name};
#end
}
pageDto.java
##引入宏定義
$!init
$!define
##定義初始變量
#set($tableName=$tool.append($tableInfo.name,"PageDto"))
##設置回調
$!callback.setFileName($tool.append($tableName,".java"))
$!callback.setSavePath($tool.append($tableInfo.savePath,"/dto/page"))
##使用宏定義設置包後綴
#setPackageSuffix("dto.page")
##使用全局變量實現默認包導入
$!autoImport
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import java.io.Serializable;
import lombok.EqualsAndHashCode;
import java.util.Date;
#tableComment("Dto")
@Getter
@Setter
@ToString
@EqualsAndHashCode
@ApiModel(value = "$!{tableInfo.comment}分頁查詢Response", description = "$!{tableInfo.comment}分頁查詢響應")
public class $!{tableName} implements Serializable {
private static final long serialVersionUID = $!tool.serial();
#foreach($column in $tableInfo.fullColumn)
/**
* $!{column.name}
*/
#if(${column.comment})@ApiModelProperty(name = "$!{column.name}", value = "${column.comment}" #if($!{tool.getClsNameByFullName($column.type)} == 'Integer') , example = "1" #end) #end
private $!{tool.getClsNameByFullName($column.type)} $!{column.name};
#end
}
queryArgs.java
##引入宏定義
$!init
$!define
##定義初始變量
#set($tableName=$tool.append($tableInfo.name,"QueryArgs"))
##設置回調
$!callback.setFileName($tool.append($tableName,".java"))
$!callback.setSavePath($tool.append($tableInfo.savePath,"/controller/args"))
##使用宏定義設置包後綴
#setPackageSuffix("controller.args")
##使用全局變量實現默認包導入
$!autoImport
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import java.io.Serializable;
import java.util.Date;
#tableComment("Args")
@Getter
@Setter
@ToString
@ApiModel(value = "$!{tableInfo.comment}條件查詢Request", description = "$!{tableInfo.comment}條件查詢入參")
public class $!{tableName} implements Serializable {
private static final long serialVersionUID = $!tool.serial();
#foreach($column in $tableInfo.fullColumn)
/**
* $!{column.name}
*/
#if(${column.comment})@ApiModelProperty(name = "$!{column.name}", value = "${column.comment}" #if($!{tool.getClsNameByFullName($column.type)} == 'Integer') , example = "1" #end) #end
private $!{tool.getClsNameByFullName($column.type)} $!{column.name};
#end
}
dto.java
##引入宏定義
$!init
$!define
##定義初始變量
#set($tableName=$tool.append($tableInfo.name,"Dto"))
##設置回調
$!callback.setFileName($tool.append($tableName,".java"))
$!callback.setSavePath($tool.append($tableInfo.savePath,"/dto"))
##使用宏定義設置包後綴
#setPackageSuffix("dto")
##使用全局變量實現默認包導入
$!autoImport
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import java.io.Serializable;
import lombok.EqualsAndHashCode;
#tableComment("查詢響應類")
@Getter
@Setter
@ToString
@EqualsAndHashCode
@ApiModel(value = "$!{tableInfo.comment}查詢Response", description = "$!{tableInfo.comment}查詢響應")
public class $!{tableName} implements Serializable {
/**
* 序列號
*/
private static final long serialVersionUID = $!tool.serial();
#foreach($column in $tableInfo.fullColumn)
/**
* ${column.comment}
*/
#if(${column.comment})@ApiModelProperty(name = "$!{column.name}", value = "${column.comment}") #end
private $!{tool.getClsNameByFullName($column.type)} $!{column.name};
#end
}
addEdit.vue
##新增,編輯,詳情頁面
##引入宏定義
$!init
$!define
##設置保存名稱與保存位置
$!callback.setFileName("addEdit.vue")
#set($tempIndex = $!tableInfo.savePackageName.lastIndexOf('.') + 1)
##set($mapppath=$tableInfo.savePackageName.substring($tempIndex))
$!callback.setSavePath($tool.append($modulePath, "/src/main/resources/mapper/",
$tool.firstLowerCase($!{tableInfo.name}),"Manage/"))
##拿到主鍵
#if(!$tableInfo.pkColumn.isEmpty())
#set($pk = $tableInfo.pkColumn.get(0))
#end
<template>
<!-- 新增編輯頁面 -->
<el-dialog :title="textMap[dialogStatus]" :visible.sync="dialogFormVisible" width="500px" :close-on-click-modal="false">
<el-form ref="dataForm" :rules="rules" :model="temp" label-position="right" label-width="100px">
#foreach($column in $tableInfo.otherColumn)
<el-form-item label="${column.comment}" prop="$!{column.name}">
<el-input v-model.trim="temp.$!{column.name}" maxlength="50" :disabled="dialogStatus=='detail'" />
</el-form-item>
#end
</el-form>
<div slot="footer" class="dialog-footer">
<el-button :loading="btnLoading" @click="dialogFormVisible = false">
取消
</el-button>
<el-button v-show="dialogStatus!=='detail'" :loading="btnLoading" type="primary" @click="dialogStatus=='detail'?createData():updateData()">
提交
</el-button>
</div>
</el-dialog>
</template>
<script>
import { create$!{tableInfo.name}, update$!{tableInfo.name} } from '@/api/$tool.firstLowerCase($tool.append($!{tableInfo.name}, "Manage"))'
import waves from '@/directive/waves' // waves directive
export default {
name: '$!{tableInfo.name}AddEdit',
directives: { waves },
props: {
// 狀態
dialogStatus: { type: String, default: 'detail' }
},
data() {
return {
btnLoading: false,
temp: {
#foreach($column in $tableInfo.otherColumn)
## 設置默認值
#if($tool.newHashSet("java.lang.String").contains($column.type))
#set($default= "''")
#elseif($tool.newHashSet("java.lang.Boolean", "boolean").contains($column.type))
#set($default= true)
#elseif($tool.newHashSet("java.lang.Byte", "byte").contains($column.type))
#set($default= 0)
#elseif($tool.newHashSet("java.lang.Integer", "int", "java.lang.Short", "short").contains($column.type))
#set($default= 0)
#elseif($tool.newHashSet("java.lang.Long", "long").contains($column.type))
#set($default= 0)
#elseif($tool.newHashSet("java.lang.Float", "float", "java.lang.Double", "double").contains($column.type))
#set($default= 0.0)
#elseif($tool.newHashSet("java.util.Date", "java.sql.Timestamp", "java.time.Instant", "java.time.LocalDateTime", "java.time.OffsetDateTime", " java.time.ZonedDateTime").contains($column.type))
#set($default= "''")
#elseif($tool.newHashSet("java.sql.Date", "java.time.LocalDate").contains($column.type))
#set($default= "''")
#else
##其他類型
#set($default= "''")
#end
$!{column.name}: $default,
#end
${pk.name}: undefined
},
listQuery: {
systemStatus: 1
},
dialogFormVisible: false,
refreshParent: false,
refreshType: 1,
textMap: {
detail: '詳情',
update: '編輯',
create: '新增'
},
rules: {
#foreach($column in $tableInfo.otherColumn)
$!{column.name}: [{ required: true,message: '請輸入${column.comment}', trigger: 'blur' }],
#end
}
}
},
watch: {
dialogFormVisible(val) {
if (!val) {
this.$emit('closeDialog', this.refreshParent, this.refreshType)
}
}
},
methods: {
open(row) {
this.refreshParent = false
this.resetTemp()
if (row) {
this.temp = Object.assign({}, row) // copy obj
}
this.dialogFormVisible = true
this.$nextTick(() => {
this.$refs['dataForm'].clearValidate()
})
},
resetTemp() {
this.temp = {
#foreach($column in $tableInfo.otherColumn)
## 設置默認值
#if($tool.newHashSet("java.lang.String").contains($column.type))
#set($default= "''")
#elseif($tool.newHashSet("java.lang.Boolean", "boolean").contains($column.type))
#set($default= true)
#elseif($tool.newHashSet("java.lang.Byte", "byte").contains($column.type))
#set($default= 0)
#elseif($tool.newHashSet("java.lang.Integer", "int", "java.lang.Short", "short").contains($column.type))
#set($default= 0)
#elseif($tool.newHashSet("java.lang.Long", "long").contains($column.type))
#set($default= 0)
#elseif($tool.newHashSet("java.lang.Float", "float", "java.lang.Double", "double").contains($column.type))
#set($default= 0.0)
#elseif($tool.newHashSet("java.util.Date", "java.sql.Timestamp", "java.time.Instant", "java.time.LocalDateTime", "java.time.OffsetDateTime", " java.time.ZonedDateTime").contains($column.type))
#set($default= "''")
#elseif($tool.newHashSet("java.sql.Date", "java.time.LocalDate").contains($column.type))
#set($default= "''")
#else
##其他類型
#set($default= "''")
#end
$!{column.name}: $default,
#end
${pk.name}: undefined
}
},
createData() {
#[[this.$refs['dataForm'].validate((valid) => { ]]#
if (valid) {
this.btnLoading = true
create$!{tableInfo.name}(this.temp).then(() => {
this.btnLoading = false
this.refreshParent = true
this.refreshType = 1
this.dialogFormVisible = false
this.$notify({
title: '成功',
message: '添加成功',
type: 'success',
duration: 2000
})
}).catch(() => {
this.btnLoading = false
})
}
})
},
updateData() {
#[[this.$refs['dataForm'].validate((valid) => {]]#
if (valid) {
this.btnLoading = true
update$!{tableInfo.name}(this.temp).then(() => {
this.btnLoading = false
this.refreshParent = true
this.refreshType = 2
this.dialogFormVisible = false
this.$notify({
title: '成功',
message: '更新成功',
type: 'success',
duration: 2000
})
}).catch(() => {
this.btnLoading = false
})
}
})
}
}
}
</script>
api.js
##JS代碼
##引入宏定義
$!init
$!define
##設置保存名稱與保存位置
$!callback.setFileName($tool.firstLowerCase($tool.append($!{tableInfo.name}, "Manage.js")))
#set($tempIndex = $!tableInfo.savePackageName.lastIndexOf('.') + 1)
##set($mapppath=$tableInfo.savePackageName.substring($tempIndex))
$!callback.setSavePath($tool.append($modulePath, "/src/main/resources/mapper/",
$tool.firstLowerCase($!{tableInfo.name}),"Manage/"))
##拿到主鍵
#if(!$tableInfo.pkColumn.isEmpty())
#set($pk = $tableInfo.pkColumn.get(0))
#end
import request from '@/utils/request'
//接口前綴
const sys_prefix = '/sys'
//分頁
export function get$!{tableInfo.name}Page(query) {
return request({
url: sys_prefix + '/$tool.firstLowerCase($!{tableInfo.name})s/page',
method: 'get',
params: query
})
}
//列表
export function get$!{tableInfo.name}List(data) {
return request({
url: sys_prefix + '/$tool.firstLowerCase($!{tableInfo.name})s/list',
method: 'get',
params: data
})
}
//詳情
export function get$!{tableInfo.name}Detail(data) {
return request({
url: sys_prefix + '/$tool.firstLowerCase($!{tableInfo.name})s/' + data.${pk.name},
method: 'get',
data
})
}
//新增
export function create$!{tableInfo.name}(data) {
return request({
url: sys_prefix + '/$tool.firstLowerCase($!{tableInfo.name})s',
method: 'post',
data
})
}
//更新
export function update$!{tableInfo.name}(data) {
return request({
url: sys_prefix + '/$tool.firstLowerCase($!{tableInfo.name})s',
method: 'put',
data
})
}
//刪除
export function $tool.append("delete",$!{tableInfo.name})(data) {
return request({
url: sys_prefix + '/$tool.firstLowerCase($!{tableInfo.name})s/' + data.${pk.name},
method: 'delete',
data
})
}
index.vue
##列表頁面
##引入宏定義
$!init
$!define
##設置保存名稱與保存位置
$!callback.setFileName("index.vue")
#set($tempIndex = $!tableInfo.savePackageName.lastIndexOf('.') + 1)
##set($mapppath=$tableInfo.savePackageName.substring($tempIndex))
$!callback.setSavePath($tool.append($modulePath, "/src/main/resources/mapper/",
$tool.firstLowerCase($!{tableInfo.name}),"Manage/"))
##拿到主鍵
#if(!$tableInfo.pkColumn.isEmpty())
#set($pk = $tableInfo.pkColumn.get(0))
#end
<template>
<div
v-loading="fullLoading"
class="app-container"
:element-loading-text="fullLoadingTitle"
element-loading-spinner="el-icon-loading">
<div class="filter-container">
<label class="el-form-item__label custom-label">XXX:</label>
<el-input v-model="listQuery.keyWords" placeholder="請輸入XXX" style="width: 150px;" class="filter-item" @keyup.enter.native="handleFilter" />
<label class="el-form-item__label custom-label">XXX日期:</label>
<el-date-picker
v-model="timeSelect"
class="filter-item"
type="daterange"
start-placeholder="開始日期"
end-placeholder="結束日期"
:default-time="['00:00:00', '23:59:59']"
@change="timeChange"/>
<el-button v-permission="['VERSION_MNG.query']" v-waves class="filter-item" type="primary" icon="el-icon-search" @click="handleFilter">
查詢
</el-button>
<el-button v-permission="['VERSION_MNG.add']" class="filter-item pull-right" style="margin-right: 10px;" type="primary" icon="el-icon-edit" @click="openDialog(null, 'create')">
新增
</el-button>
</div>
<el-table
:key="tableKey" v-loading="listLoading" :data="list"
border fit highlight-current-row
style="width: 100%;">
#foreach($column in $tableInfo.otherColumn)
<el-table-column label="${column.comment}" prop="$!{column.name}" align="center" min-width="80">
<template slot-scope="scope">
#if($column == $tableInfo.otherColumn.get(0))
<span class="link-type" @click="openDialog(scope.row, 'detail')">{{ scope.row.$!{column.name} }}</span>
#else
<span>{{ scope.row.$!{column.name} }}</span>
#end
</template>
</el-table-column>
#end
<el-table-column label="操作" align="center" width="180" class-name="small-padding fixed-width">
<template slot-scope="{row}">
<el-link v-permission="['VERSION_MNG.add']" type="info" size="mini" @click="openDialog(row, 'detail')">
詳情
</el-link>
<el-link v-permission="['VERSION_MNG.edit']" type="primary" size="mini" @click="openDialog(row, 'update')">
編輯
</el-link>
<el-link v-permission="['VERSION_MNG.delete']" type="danger" size="mini" @click="handleDelete(row)">
刪除
</el-link>
</template>
</el-table-column>
</el-table>
<pagination v-show="total>0" :total="total" :page.sync="listQuery.pageNum" :limit.sync="listQuery.pageSize" @pagination="getList" />
<AddEditDialog ref="addEditDialog" :dialog-status="dialogStatus" @closeDialog="closeDialog" />
</div>
</template>
<script>
import { get$!{tableInfo.name}Page, get$!{tableInfo.name}Detail, $tool.append("delete",$!{tableInfo.name}) } from '@/api/$tool.firstLowerCase($tool.append($!{tableInfo.name}, "Manage"))'
import waves from '@/directive/waves' // waves directive
import Pagination from '@/components/Pagination' // secondary package based on el-pagination
import AddEditDialog from './addEdit.vue'
import checkPermission from '@/utils/permission' // 權限判斷函數
export default {
name: '$!{tableInfo.name}Table',
components: { Pagination, AddEditDialog },
directives: { waves },
filters: {
statusFilter(status) {
const statusMap = {
2: 'warging',
1: 'success'
}
return statusMap[status]
}
},
data() {
return {
btnLoading: false,
fullLoading: false,
fullLoadingTitle: '加載中',
tableKey: 0,
list: null,
total: 0,
listLoading: false,
listQuery: {
pageNum: 1,
pageSize: 10,
keyWords: '',
startTime: '',
endTime: ''
},
timeSelect: [],
dialogStatus: '',
authFormVisible: false,
authData: null
}
},
created() {
this.getList()
},
methods: {
checkPermission,
//分頁查詢
getList() {
if (this.listLoading) {
return
}
this.listLoading = true
get$!{tableInfo.name}Page(this.listQuery).then(response => {
this.list = response.data.records
this.total = response.data.total
this.listLoading = false
})
},
//時間選擇事件
timeChange() {
if (this.timeSelect) {
this.listQuery.startTime = this.timeSelect[0]
this.listQuery.endTime = this.timeSelect[1]
} else {
this.listQuery.startTime = ''
this.listQuery.endTime = ''
}
},
handleFilter() {
this.listQuery.pageNum = 1
this.getList()
},
getSortClass: function(key) {
const sort = this.listQuery.sort
return sort === `+${key}` ? 'ascending' : sort === `-${key}` ? 'descending' : ''
},
openDialog(row, state) {
this.dialogStatus = state
this.$refs.addEditDialog.open(row)
},
// 子窗口頁面關閉後觸發的本頁面方法
closeDialog(refreshParent, refreshType) {
this.dialogStatus = null
// 子窗口關閉後本頁面是否刷新由子頁面傳遞參數決定,1標示頁碼迴歸到1刷新,頁面爲2標示頁碼留在當前頁面進行刷新
if (refreshParent) {
if (refreshType === 2) {
this.getList()
} else {
this.handleFilter()
}
}
},
//刪除
handleDelete(row) {
this.$confirm('確認刪除該數據嗎?', '提示', {
confirmButtonText: '確定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
this.fullLoading = true
this.fullLoadingTitle = '刪除中'
$tool.append("delete",$!{tableInfo.name})(row).then(() => {
this.$message({
message: '操作成功',
type: 'success'
})
this.fullLoading = false
this.getList()
}).catch(error => {
this.fullLoading = false
})
}).catch(() => {})
}
}
}
</script>
生成
模版設置好了過後,就可以開始生成了。
可以選擇多張表
右鍵生成
生成時,需要注意幾點,一定要選擇好對應的Package,不然會生成錯地方。還有就是可以勾選一下禁止提示。不然生成很多的話會一直彈框提示。
項目結構
生成後
到這裏,就差不多了,easyCode可以導入導出,但是都是導出到他的官網,給你生成一個token。所以這裏就沒有使用這種方式導出來,而是直接貼出了我們的模版。
好了,到這裏就差不多了!接下來我們將使用token的方式來進行登錄,並且自定義錯誤的返回提示。
----------------------------------------------------------
項目的源碼地址:https://gitee.com/gzsjd/fast
----------------------------------------------------------