1、在IDEA界面选择选择如下
2、配置数据库驱动
3、配置数据库账户和URL信息
URL说明(只需要修改数据库地址和库名即可):jdbc:mysql://localhost:3306/dolabor?useUnicode=true&characterEncoding=UTF-8&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=UTC
4、连接数据库成功,右击选择数据库需要使用的库、表
5、搜索插件EasyCode数据库逆向插件
6、修改EasyCode的插件模板去除表名前缀
7、将需要的模板加上去前缀代码即可(内容如下)
## 去掉t_表前缀
$!init
8、由于当前下载插件带的service模板存在异常故修改备份于此(修改成自己开发习惯)
注意去表头配置:
##去掉表的t_前缀
$!tableInfo.setName($tool.getClassName($tableInfo.obj.name.replaceFirst("t_","")))
图片如下:
entity.java 模板
##引入宏定义
## 去掉t_表前缀
$!init
$!define
##使用宏定义设置回调(保存位置与文件后缀)
#save("/entity", ".java")
##使用宏定义设置包后缀
#setPackageSuffix("entity")
##拿到主键
#if(!$tableInfo.pkColumn.isEmpty())
#set($pk = $tableInfo.pkColumn.get(0).name)
#end
import $!{tableInfo.savePackageName}.util.QueryRequest;
##使用全局变量实现默认包导入
$!autoImport
import java.io.Serializable;
import io.swagger.annotations.*;
import lombok.Data;
import javax.persistence.Id;
import javax.persistence.Table;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
##使用宏定义实现类注释信息
#tableComment("实体类")
@Data
@Table(name = "$!tableInfo.obj.name")
@ApiModel("$tableInfo.comment")
public class $!{tableInfo.name} extends QueryRequest implements Serializable {
private static final long serialVersionUID = $!tool.serial();
#foreach($column in $tableInfo.fullColumn)
#if(${column.comment})/**
* ${column.comment}
*/#end
##给主键标识和新增返回主键
#if(${column.name.equals($pk)})
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)#end
@ApiModelProperty("$column.comment")
private $!{tool.getClsNameByFullName($column.type)} $!{column.name};
#end
}
dao.java 模板
## 去掉t_表前缀
$!init
##定义初始变量
#set($tableName = $tool.append($tableInfo.name, "Mapper"))
##设置回调
$!callback.setFileName($tool.append($tableName, ".java"))
$!callback.setSavePath($tool.append($tableInfo.savePath, "/dao/mapper"))
##拿到主键
#if(!$tableInfo.pkColumn.isEmpty())
#set($pk = $tableInfo.pkColumn.get(0))
#end
#if($tableInfo.savePackageName)package $!{tableInfo.savePackageName}.#{end}dao.mapper;
import $!{tableInfo.savePackageName}.base.TkBaseMapper;
import $!{tableInfo.savePackageName}.entity.$!{tableInfo.name};
/**
* $!{tableInfo.comment}($!{tableInfo.name})表数据库访问层
*
* @author $!author
* @since $!time.currTime()
*/
public interface $!{tableName} extends TkBaseMapper<$!{tableInfo.name}> {
}
service.java
## 去掉t_表前缀
$!init
##定义初始变量
#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
#if($tableInfo.savePackageName)package $!{tableInfo.savePackageName}.#{end}service;
import $!{tableInfo.savePackageName}.entity.$!{tableInfo.name};
/**
* $!{tableInfo.comment}($!{tableInfo.name})表服务实现类
*
* @author $!author
* @since $!time.currTime()
*/
public interface $!{tableName} {
/**
* 保存数据
*
* @param userId 用户ID
* @param $!tool.firstLowerCase($!{tableInfo.name}) 实例对象
* @return 是否成功
*/
int save(Integer userId, $!{tableInfo.name} $!tool.firstLowerCase($!{tableInfo.name}));
/**
* 新增数据
*
* @param userId 用户ID
* @param $!tool.firstLowerCase($!{tableInfo.name}) 实例对象
* @return 是否成功
*/
int insert(Integer userId, $!{tableInfo.name} $!tool.firstLowerCase($!{tableInfo.name}));
/**
* 通过主键删除数据
*
* @param userId 用户ID
* @param $!pk.name 主键
* @return 是否成功
*/
int delete(Integer userId, $!pk.shortType $!pk.name);
/**
* 修改数据
*
* @param userId 用户ID
* @param $!tool.firstLowerCase($!{tableInfo.name}) 实例对象
* @return 是否成功
*/
int update(Integer userId, $!{tableInfo.name} $!tool.firstLowerCase($!{tableInfo.name}));
/**
* 通过ID查询单条数据
*
* @param $!pk.name 主键
* @return 实例对象
*/
$!{tableInfo.name} queryById($!pk.shortType $!pk.name);
/**
* 查询多条数据
*
* @param userId 用户ID
* @param $!tool.firstLowerCase($!{tableInfo.name}) 查询条数
* @return 对象列表
*/
PageWrapper<$!{tableInfo.name}> list(Integer userId, $!{tableInfo.name} $!tool.firstLowerCase($!{tableInfo.name}));
}
serviceImpl.java模板
## 去掉t_表前缀
$!init
##定义初始变量
#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
##拿到createBy其它
#if(!$tableInfo.otherColumn.isEmpty())
#foreach($column in $tableInfo.otherColumn)
#if($column.name.equals("createBy"))
#set($createBy = $column.name)
#end
#if($column.name.equals("updateBy"))
#set($updateBy = $column.name)
#end
#if($column.name.equals("updateTime"))
#set($updateTime = $column.name)
#end
#if($column.name.equals("flag"))
#set($flag = $column.name)
#end
#end
#end
## 截取对象名的第一个字符串
#set($length1 = $tool.firstLowerCase($!{tableInfo.name}).substring(0, 1))
#if($tableInfo.savePackageName)package $!{tableInfo.savePackageName}.#{end}service.impl;
import $!{tableInfo.savePackageName}.entity.$!{tableInfo.name};
import $!{tableInfo.savePackageName}.enums.DataEnum;
import $!{tableInfo.savePackageName}.dao.mapper.$!{tableInfo.name}Mapper;
import $!{tableInfo.savePackageName}.service.$!{tableInfo.name}Service;
import org.springframework.stereotype.Service;
import java.util.Date;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import javax.annotation.Resource;
/**
* $!{tableInfo.comment}($!{tableInfo.name})表服务实现类
*
* @author $!author
* @since $!time.currTime()
*/
@Service("$!tool.firstLowerCase($!{tableInfo.name})Service")
public class $!{tableName} implements $!{tableInfo.name}Service {
/**
* 服务对象
*/
@Resource
private $!{tableInfo.name}Mapper $!tool.firstLowerCase($!{tableInfo.name})Mapper;
/**
* 保存数据
*
* @param userId 用户ID
* @param $!tool.firstLowerCase($!{tableInfo.name}) 实例对象
* @return 是否成功
*/
@Override
public int save(Integer userId, $!{tableInfo.name} $!tool.firstLowerCase($!{tableInfo.name})) {
if($!{tool.firstLowerCase($!{tableInfo.name})}.get$!{tool.firstUpperCase($!{pk.name})}() == null){
return insert(userId, $!tool.firstLowerCase($!{tableInfo.name}));
} else {
return update(userId,$!tool.firstLowerCase($!{tableInfo.name}));
}
}
/**
* 新增数据
*
* @param userId 用户ID
* @param $!tool.firstLowerCase($!{tableInfo.name}) 实例对象
* @return 是否成功
*/
@Override
public int insert(Integer userId, $!{tableInfo.name} $!tool.firstLowerCase($!{tableInfo.name})) {
$!{tool.firstLowerCase($!{tableInfo.name})}.set$!{tool.firstUpperCase($!{createBy})}(userId);
return $!{tool.firstLowerCase($!{tableInfo.name})}Mapper.insertSelective($!tool.firstLowerCase($!{tableInfo.name}));
}
/**
* 通过主键删除数据
*
* @param userId 用户ID
* @param $!pk.name 主键
* @return 是否成功
*/
@Override
public int delete(Integer userId, $!pk.shortType $!pk.name) {
$!{tableInfo.name} $!tool.firstLowerCase($!{tableInfo.name}) = $!{tool.firstLowerCase($!{tableInfo.name})}Mapper.selectByPrimaryKey($!pk.name);
$!{tool.firstLowerCase($!{tableInfo.name})}.set$!{tool.firstUpperCase($!{updateBy})}(userId);
$!{tool.firstLowerCase($!{tableInfo.name})}.set$!{tool.firstUpperCase($!{updateTime})}(new Date());
$!{tool.firstLowerCase($!{tableInfo.name})}.set$!{tool.firstUpperCase($!{flag})}(DataEnum.FLAG_STATUS_INVALID.getCode());
return $!{tool.firstLowerCase($!{tableInfo.name})}Mapper.updateByPrimaryKeySelective($!tool.firstLowerCase($!{tableInfo.name}));
}
/**
* 修改数据
*
* @param $!tool.firstLowerCase($!{tableInfo.name}) 实例对象
* @return 是否成功
*/
@Override
public int update(Integer userId, $!{tableInfo.name} $!tool.firstLowerCase($!{tableInfo.name})){
$!{tableInfo.name} $!{length1} = $!{tool.firstLowerCase($!{tableInfo.name})}Mapper.selectByPrimaryKey($!{tool.firstLowerCase($!{tableInfo.name})}.get$!{tool.firstUpperCase($!{pk.name})}());
// FIXME 待完善
return $!{tool.firstLowerCase($!{tableInfo.name})}Mapper.updateByPrimaryKeySelective($!{length1});
}
/**
* 通过ID查询单条数据
*
* @param $!pk.name 主键
* @return 实例对象
*/
@Override
public $!{tableInfo.name} queryById($!pk.shortType $!pk.name){
return $!{tool.firstLowerCase($!{tableInfo.name})}Mapper.selectByPrimaryKey($!pk.name);
}
/**
* 查询多条数据
*
* @param userId 用户ID
* @param $!tool.firstLowerCase($!{tableInfo.name}) 查询条数
* @return 对象列表
*/
@Override
public PageWrapper<$!{tableInfo.name}> list(Integer userId, $!{tableInfo.name} $!tool.firstLowerCase($!{tableInfo.name})) {
PageHelper.startPage($!{tool.firstLowerCase($!{tableInfo.name})}.getPageNum(), $!{tool.firstLowerCase($!{tableInfo.name})}.getPageSize());
$!{tool.firstLowerCase($!{tableInfo.name})}.set$!{tool.firstUpperCase($!{flag})}(DataEnum.FLAG_STATUS_VALID.getCode());
PageInfo<$!{tableInfo.name}> page = new PageInfo<>($!{tool.firstLowerCase($!{tableInfo.name})}Mapper.select($!{tool.firstLowerCase($!{tableInfo.name})}));
PageHelper.clearPage();
return new PageWrapper<>(page);
}
}
controller.java模板
## 去掉t_表前缀
$!init
##定义初始变量
#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
#if($tableInfo.savePackageName)package $!{tableInfo.savePackageName}.#{end}controller;
import $!{tableInfo.savePackageName}.entity.$!{tableInfo.name};
import $!{tableInfo.savePackageName}.service.$!{tableInfo.name}Service;
import org.springframework.web.bind.annotation.*;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import javax.annotation.Resource;
import $!{tableInfo.savePackageName}.vo.ResponseHelper;
import $!{tableInfo.savePackageName}.vo.ResponseModel;
/**
* $!{tableInfo.comment}($!{tableInfo.name})表控制层
*
* @author $!author
* @since $!time.currTime()
*/
@Api(tags = "$!{tableInfo.comment}($!{tableInfo.name})")
@RestController
@RequestMapping("$!tool.firstLowerCase($tableInfo.name)")
public class $!{tableName} {
/**
* 服务对象
*/
@Resource
private $!{tableInfo.name}Service $!tool.firstLowerCase($tableInfo.name)Service;
/**
* 新增/修改数据
*
* @param userId 用户ID
* @param $!tool.firstLowerCase($!{tableInfo.name}) 实例对象
* @return 是否成功
*/
@PostMapping("save")
@ApiOperation(value = "新增/修改", notes = "新增/修改$!{tableInfo.comment}的一条数据")
@RequiresPermissions(logical = Logical.OR, value = {"$!tool.firstLowerCase($!{tableInfo.name}):insert", "$!tool.firstLowerCase($!{tableInfo.name}):edit"})
public ResponseModel save(@ApiParam(value = "用户ID", required = false) @UserId String userId, @ApiParam(value = "$!{tableInfo.comment}对象", required = true) @RequestBody @Validated $!{tableInfo.name} $!tool.firstLowerCase($!{tableInfo.name})) {
return ResponseHelper.success($!{tool.firstLowerCase($!{tableInfo.name})}Service.save(Integer.valueOf(userId), $!tool.firstLowerCase($!{tableInfo.name})));
}
/**
* 通过主键删除数据
*
* @param userId 用户ID
* @param $!pk.name 主键
* @return 是否成功
*/
@DeleteMapping("delete/{$!{pk.name}}")
@ApiOperation(value = "删除单条数据", notes = "删除主键$!{pk.name}的单条数据")
@RequiresPermissions(logical = Logical.OR, value = {"$!tool.firstLowerCase($!{tableInfo.name}):delete"})
public ResponseModel delete(@ApiParam(value = "用户ID", required = false) @UserId String userId, @ApiParam(value = "$!{tableInfo.comment}主键$!{pk.name}", required = true) @PathVariable("$!{pk.name}") $!pk.shortType $!pk.name) {
return ResponseHelper.success($!{tool.firstLowerCase($!{tableInfo.name})}Service.delete(Integer.valueOf(userId), $!pk.name));
}
/**
* 通过ID查询单条数据
*
* @param $!{pk.name} 主键
* @return 实例对象
*/
@GetMapping("queryById/{$!{pk.name}}")
@ApiOperation(value = "查询单条数据", notes = "通过$!{pk.name}查询单条数据}")
public ResponseModel queryById(@ApiParam(value = "$!{tableInfo.comment}主键$!{pk.name}", required = true) @PathVariable("$!{pk.name}") $!pk.shortType $!{pk.name}){
return ResponseHelper.success($!{tool.firstLowerCase($!{tableInfo.name})}Service.queryById($!{pk.name}));
}
/**
* 查询多条数据
*
* @param userId 用户ID
* @param $!tool.firstLowerCase($!{tableInfo.name}) 查询条数
* @return 对象列表
*/
@PostMapping("list")
@ApiOperation(value = "列表", notes = "查询$!{tableInfo.comment}的多条数据")
public ResponseModel list(@ApiParam(value = "用户ID", required = false) @UserId String userId, @ApiParam(value = "$!{tableInfo.comment}对象", required = true) @RequestBody $!{tableInfo.name} $!tool.firstLowerCase($!{tableInfo.name})) {
return ResponseHelper.success($!{tool.firstLowerCase($!{tableInfo.name})}Service.list(Integer.valueOf(userId), $!tool.firstLowerCase($!{tableInfo.name})));
}
}
mapper.xml模板
## 去掉t_表前缀
$!init
##引入mybatis支持
$!mybatisSupport
##设置保存名称与保存位置
$!callback.setFileName($tool.append($!{tableInfo.name}, "Dao.xml"))
$!callback.setSavePath($tool.append($modulePath, "/src/main/resources/mapping"))
##拿到主键
#if(!$tableInfo.pkColumn.isEmpty())
#set($pk = $tableInfo.pkColumn.get(0))
#end
#foreach($column in $tableInfo.fullColumn)
#end
insert into $!{tableInfo.obj.parent.name}.$!{tableInfo.obj.name}(#foreach($column in $tableInfo.otherColumn)$!column.obj.name#if($velocityHasNext), #end#end)
values (#foreach($column in $tableInfo.otherColumn)#{$!{column.name}}#if($velocityHasNext), #end#end)
update $!{tableInfo.obj.parent.name}.$!{tableInfo.obj.name}
#foreach($column in $tableInfo.otherColumn)
$!column.obj.name = #{$!column.name},
#end
where $!pk.obj.name = #{$!pk.name}
delete from $!{tableInfo.obj.parent.name}.$!{tableInfo.obj.name} where $!pk.obj.name = #{$!pk.name}
9、选择对应的表文件右击创建所需的文件
10、在弹出的对话框操作即可
Tips:引入jar包 (版本号自己选择)
io.springfox
springfox-swagger2
2.9.2
io.springfox
springfox-swagger-ui
2.9.2
com.github.xiaoymin
knife4j-spring-boot-starter
2.0.3
tk.mybatis
mapper-spring-boot-starter
2.1.5
com.github.pagehelper
pagehelper-spring-boot-starter
1.2.5
org.apache.shiro
shiro-spring
1.4.0
org.apache.commons
commons-lang3
com.auth0
java-jwt
3.8.1
实体base类:
package com.automatically.create.project.util;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.persistence.Transient;
import java.io.Serializable;
/**
* @author pc
*/
@Data
@ApiModel("base类")
public class QueryRequest implements Serializable {
@Transient
private static final long serialVersionUID = -32472298260769753L;
@Transient
@ApiModelProperty("页码数")
private int pageSize = 10;
@Transient
@ApiModelProperty("页码号")
private int pageNum = 1;
}
封装PageWrapper分页文件:
import com.github.pagehelper.PageInfo;
import lombok.Data;
import java.io.Serializable;
import java.util.List;
/**
* @author pc
*/
@Data
public class PageWrapper implements Serializable {
private List list;
private int total;
public PageWrapper(PageInfo pageInfo) {
this.list = pageInfo.getList();
this.total = (int) pageInfo.getTotal();
}
}
DataEnum:
package com.example.wosen.enums;
import lombok.Getter;
/**
* @author pc
*/
@Getter
public enum DataEnum {
FLAG_STATUS_INVALID(1, "数据无效"),
FLAG_STATUS_VALID(0, "数据有效");
/**
* 请求响应码
*/
private Integer code;
/**
* 请求响应说明
*/
private String desc;
DataEnum(Integer code, String desc) {
this.code = code;
this.desc = desc;
}
}
application启动类加上:
import tk.mybatis.spring.annotation.MapperScan;
@MapperScan("com.***.***.dao.mapper")
package com.automatically.create.project.base;
import tk.mybatis.mapper.common.BaseMapper;
import tk.mybatis.mapper.common.ExampleMapper;
import tk.mybatis.mapper.common.MySqlMapper;
/**
* TK 泛型
* @author pc
* @param
*/
public interface TkBaseMapper extends BaseMapper, ExampleMapper, MySqlMapper {
}
import com.earn.money.enums.ResultCode;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.io.Serializable;
/**
* @author pc
* 统一返回相应参数实体类
*/
@Data
@ApiModel("统一返回相应参数实体类")
public class ResponseModel implements Serializable {
private static final long serialVersionUID = -1241360949457314497L;
@ApiModelProperty("返回实体")
private T data;
@ApiModelProperty("响应消息")
private String message;
@ApiModelProperty("响应码")
private Integer code;
public ResponseModel(T data) {
this.data = data;
this.code = ResultCode.SUCCESS.getCode();
this.message = ResultCode.SUCCESS.getMessage();
}
public ResponseModel(Integer code, String message) {
this.message = message;
this.code = code;
}
public ResponseModel(T data, ResultCode resultCode) {
this.data = data;
this.message = resultCode.getMessage();
this.code = resultCode.getCode();
}
public ResponseModel(T data, Integer code, String message) {
this.data = data;
this.code = code;
this.message = message;
}
}
import com.earn.money.enums.ResultCode;
import java.io.Serializable;
/**
* 统一返回相应参数
* @author pc
*/
public class ResponseHelper implements Serializable {
/**
* 操作成功默认: code + msg
* @param model
* @param
* @return
*/
public static ResponseModel success(T model) {
return successWith(model, ResultCode.SUCCESS);
}
/**
* 作成功自定义错误: code + msg
* @param t
* @param resultCode
* @param
* @return
*/
public static ResponseModel successWith(T t, ResultCode resultCode) {
return new ResponseModel(t, resultCode);
}
/**
* 操作失败默认: code + msg
* @param model
* @param
* @return
*/
public static ResponseModel failed(T model) {
return failedWith(model, ResultCode.ERROR);
}
/**
* 操作失败自定义错误: code + msg
* @param t
* @param resultCode
* @param
* @return
*/
public static ResponseModel failedWith(T t, ResultCode resultCode) {
return new ResponseModel<>(t, resultCode);
}
/**
* 操作失败自定义错误: code + msg
* @param message
* @param
* @return
*/
public static ResponseModel failedWith(String message) {
return new ResponseModel<>(ResultCode.VALIDATE_FAILED.getCode(), message);
}
}
import lombok.Getter;
/**
* @author BaoBao
*/
@Getter
public enum ResultCode {
// 请求信息
SUCCESS(10000, "操作成功"),
FAILED(10001, "响应失败"),
VALIDATE_FAILED(10002, "参数校验失败"),
// 系统信息
ERROR(50000, "未知错误");
/**
* 请求响应码
*/
private Integer code;
/**
* 请求响应说明
*/
private String message;
ResultCode(int code, String message){
this.code = code;
this.message = message;
}
}
package com.automatically.create.project.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* userId注解
* @author pc
*/
@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
public @interface UserId {
}
import com.example.wosen.annotation.support.UserIdHandlerMethodArgumentResolver;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import java.util.List;
/**
* userId注解
* @author pc
*/
@Configuration
public class WebMvcConfiguration implements WebMvcConfigurer {
@Override
public void addArgumentResolvers(List argumentResolvers) {
argumentResolvers.add(new UserIdHandlerMethodArgumentResolver());
}
}
package com.automatically.create.project.annotation.support;
import com.automatically.create.project.annotation.UserId;
import com.automatically.create.project.shiro.JwtUtil;
import org.apache.commons.lang3.StringUtils;
import org.springframework.core.MethodParameter;
import org.springframework.web.bind.support.WebDataBinderFactory;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.ModelAndViewContainer;
/**
* userId注解
* @author pc
* 接口说明:
* supportsParameter:用于判定是否需要处理该参数分解,返回true为需要,并会去调用下面的方法resolveArgument。
* resolveArgument:真正用于处理参数分解的方法,返回的Object就是controller方法上的形参对象。
*/
public class UserIdHandlerMethodArgumentResolver implements HandlerMethodArgumentResolver {
/**
* 获取header中的key
*/
public static final String LOGIN_TOKEN_KEY = "Authorization";
@Override
public boolean supportsParameter(MethodParameter methodParameter) {
Class> class1 = methodParameter.getParameterType();
// class1.isAssignableFrom(Class>2) 判定此 Class1 对象所表示的类或接口与指定的 Class>2 参数所表示的类或接口是否相同,或是否是其超类或超接口。如果是则返回 true;否则返回 false。
return methodParameter.hasParameterAnnotation(UserId.class) && class1.isAssignableFrom(String.class);
}
@Override
public Object resolveArgument(MethodParameter methodParameter, ModelAndViewContainer modelAndViewContainer, NativeWebRequest nativeWebRequest, WebDataBinderFactory webDataBinderFactory) {
String token = nativeWebRequest.getHeader(LOGIN_TOKEN_KEY);
if (StringUtils.isBlank(token)) {
return null;
}
if (methodParameter.getParameterType().isAssignableFrom(String.class)) {
String userId = JwtUtil.getUserId(token);
return userId;
}
return null;
}
}
JwtUtil认证中心:
package com.automatically.create.project.shiro;
import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTDecodeException;
import com.auth0.jwt.interfaces.DecodedJWT;
import lombok.extern.slf4j.Slf4j;
import java.util.Date;
/**
* JWT工具类
* @author pc
*/
@Slf4j
public class JwtUtil {
/**
* 过期毫秒数
*/
private static final long EXPIRE_TIME = 1 * 24 * 60 * 60 * 1000;
/**
* JWT中保存的用户名键
*/
private static final String USER_ID = "id";
/**
* 生成签名
* @param userId 用户id
* @param secret 用户的密码
* @return 加密的token
*/
public static String sign(String userId, String secret) {
Date date = new Date(System.currentTimeMillis() + EXPIRE_TIME);
Algorithm algorithm = Algorithm.HMAC256(secret);
// 附带username信息
return JWT.create()
.withClaim(USER_ID, userId)
.withExpiresAt(date)
.sign(algorithm);
}
/**
* 校验token是否正确
* @param token 密钥
* @param userId 用户ID
* @param secret 用户的密码
* @return 是否正确
*/
public static boolean verifyToKen(String token, String userId, String secret) {
try {
//根据密码生成JWT效验器
Algorithm algorithm = Algorithm.HMAC256(secret);
JWTVerifier verifier = JWT.require(algorithm)
.withClaim(USER_ID, userId)
.build();
//效验TOKEN
verifier.verify(token);
return true;
} catch (Exception e) {
log.error("token验证失败", e);
return false;
}
}
/**
* token验证token
* @param token
* @return
*/
public static boolean verifyToKen(String token) {
try {
JWT.decode(token);
return true;
} catch (Exception e) {
log.error("token验证失败", e);
return false;
}
}
/**
* 获取token中的用户ID
*
* @param token
* @return
*/
public static String getUserId(String token) {
try {
DecodedJWT jwt = JWT.decode(token);
return jwt.getClaim(USER_ID).asString();
} catch (JWTDecodeException e) {
return null;
}
}
}
swagger2config配置:
package com.example.wosen.config;
import com.github.xiaoymin.knife4j.spring.annotations.EnableKnife4j;
import com.google.common.collect.Lists;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.ParameterBuilder;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.schema.ModelRef;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.Parameter;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
import java.util.List;
/**
* @author BaoBao
*/
@Configuration
@EnableSwagger2
@EnableKnife4j
public class Swagger2 {
/**
* 多模块配置 是否渲染控制台
*/
private boolean enable = true;
private ApiInfo apiInfo() {
return new ApiInfoBuilder()
.title("woSen猎头")
.description("寻找发光的你")
.termsOfServiceUrl("http://192.168.110.76/")
.version("1.0")
.contact("我是你嘉哥哦~")
.build();
}
@Bean(value = "controllerApi")
public Docket controllerApi() {
ParameterBuilder pb = new ParameterBuilder();
List lp = Lists.newArrayList();
pb.name("Authorization")
.description("User Authorization")
.modelRef(new ModelRef("String"))
.parameterType("header")
.required(true)
.build();
// 根据每个方法名也知道当前方法在设置什么参数
lp.add(pb.build());
return new Docket(DocumentationType.SWAGGER_2)
.groupName("controllerApi")
.select()
.apis(RequestHandlerSelectors.basePackage("com.example.wosen.controller"))
.build()
.apiInfo(apiInfo())
.enable(enable);
}
}
跨域文件处理:
package com.example.wosen.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;
/**
* CorsConfig TODO(处理跨域)
* @author pc
*/
@Configuration
public class CorsConfig {
private CorsConfiguration buildConfig() {
CorsConfiguration corsConfiguration = new CorsConfiguration();
// 1 设置访问源地址
corsConfiguration.addAllowedOrigin("*");
// 2 设置访问源请求头
corsConfiguration.addAllowedHeader("*");
// 3 设置访问源请求方法
corsConfiguration.addAllowedMethod("*");
return corsConfiguration;
}
@Bean
public CorsFilter corsFilter() {
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
//4 对接口配置跨域设置
source.registerCorsConfiguration("/**", buildConfig());
return new CorsFilter(source);
}
}
import com.earn.money.enums.ResultCode;
import com.earn.money.vo.ResponseHelper;
import com.earn.money.vo.ResponseModel;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.ShiroException;
import org.apache.shiro.authc.AuthenticationException;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import java.io.IOException;
/**
* 针对单个指定异常捕获,并且定义错误的返回体
*
* @author BaoBao
*/
@Slf4j
@RestControllerAdvice
public class ExceptionControllerAdvice {
/**
* 捕捉shiro的异常
*
* @param e
* @return
*/
@ResponseBody
@ExceptionHandler(ShiroException.class)
public ResponseModel handleShiRoException(ShiroException e) {
log.error("handleShiRoException异常错误信息:", e);
return ResponseHelper.failedWith(e.getMessage());
}
@ResponseBody
@ExceptionHandler(AuthenticationException.class)
public ResponseModel handleAuthenticationException(AuthenticationException e) {
log.error("handleAuthenticationException异常错误信息:{}", e);
return ResponseHelper.failedWith(e.getMessage());
}
/**
* 全局API异常处理
*
* @param e
* @return
*/
@ResponseBody
@ExceptionHandler(ApiException.class)
public ResponseModel APIGlobalExceptionHandler(ApiException e) {
log.error("APIGlobalExceptionHandler异常错误信息:{}", e);
return ResponseHelper.failedWith(e.getMessage());
}
/**
* Http消息不可读异常
* @param e
* @return
*/
@ExceptionHandler(value = HttpMessageNotReadableException.class)
@ResponseBody
public ResponseModel handleParamJsonException(HttpMessageNotReadableException e) {
log.error("handleParamJsonException异常错误信息:", e);
return ResponseHelper.failedWith(e.getMessage());
}
/**
* 全局实体属性验证异常处理
*
* @param e
* @return
*/
@ResponseBody
@ExceptionHandler(MethodArgumentNotValidException.class)
public ResponseModel MethodArgumentNotValidGlobalExceptionHandler(MethodArgumentNotValidException e) {
log.error("MethodArgumentNotValidGlobalExceptionHandler异常错误信息:", e);
return ResponseHelper.failedWith(e.getMessage());
}
/**
* 空指针异常处理
*
* @param e
* @return
*/
@ResponseBody
@ExceptionHandler(NullPointerException.class)
public ResponseModel NullPointerGlobalExceptionHandler(NullPointerException e) {
log.error("NullPointerException:{}", e);
StackTraceElement stackTraceElement = e.getStackTrace()[0];
return ResponseHelper.failedWith("具体文件. " + stackTraceElement.getClassName() + ". 所属行号. " + stackTraceElement.getLineNumber());
}
/**
* jackson取值异常处理
*
* @param e
* @return
*/
@ResponseBody
@ExceptionHandler(IOException.class)
public ResponseModel IOEGlobalExceptionHandler(IOException e) {
log.error("IOEGlobalExceptionHandler异常错误信息:{}", e);
StackTraceElement stackTraceElement = e.getStackTrace()[0];
return ResponseHelper.failedWith("具体文件. " + stackTraceElement.getClassName() + ". 所属行号. " + stackTraceElement.getLineNumber());
}
/**
* 索引越界异常处理
*
* @param e
* @return
*/
@ResponseBody
@ExceptionHandler(IndexOutOfBoundsException.class)
public ResponseModel IndexOutOfBoundsGlobalExceptionHandler(IndexOutOfBoundsException e) {
log.error("IndexOutOfBoundsGlobalExceptionHandler异常错误信息:{}", e);
StackTraceElement stackTraceElement = e.getStackTrace()[3];
return ResponseHelper.failedWith("具体文件. " + stackTraceElement.getClassName() + ". 所属行号. " + stackTraceElement.getLineNumber(), ResultCode.INDEX_OUT_OF_BOUNDS);
}
/**
* 全局异常捕捉处理
*/
@ResponseBody
@ExceptionHandler(Exception.class)
public ResponseModel errorHandler(Exception e) {
log.error("errorHandler异常错误信息:", e);
return ResponseHelper.failedWith(e.getMessage(), ResultCode.ERROR);
}
}
import com.earn.money.vo.ResponseModel;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;
/**
* 全局数据响应处理
* 加上需要扫描的包
* @author BaoBao
*/
@RestControllerAdvice(basePackages = {"com.earn.money.app.controller", "com.earn.money.admin.controller", "com.earn.money.public.controller"})
public class ResponseControllerAdvice implements ResponseBodyAdvice
import com.earn.money.enums.ResultCode;
import lombok.Getter;
/**
* 针对继承的异常封装响应码和响应信息
* @author BaoBao
*/
@Getter
public class ApiException extends RuntimeException{
private static final long serialVersionUID = 3455708526465670030L;
public int code;
public String msg;
/**
* 指定响应码和其它响应信息
* @param msg
*/
public ApiException(String msg){
this(ResultCode.ERROR.getCode(), msg);
}
/**
* 其它响应码和响应信息
* @param code
* @param msg
*/
public ApiException(int code, String msg){
super(msg);
this.code = code;
this.msg = msg;
}
}
import java.lang.annotation.*;
/**
* 在Controller方法上加入改注解会自动记录日志
*
* @author pc
*/
@Documented
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Log {
/**
* 描述. 执行
*/
String description() default "";
}
/**
* 日志方面
*
* @author pc
*/
@Slf4j
@Aspect
@Component
public class LogAspect {
@Resource
private UserLogMapper userLogMapper;
/**
* 获取header中的key
*/
public static final String LOGIN_TOKEN_KEY = "Authorization";
/**
* 切入点
*/
@Pointcut("@annotation(com.rhwlkj.firefly20200330.annotation.Log)")
public void pointcut() {
}
/**
* 周围
*
* @param point
* @return
*/
@Around(value = "pointcut()")
public Object around(ProceedingJoinPoint point) {
// 定义注解处的方法结果对象
Object result;
// 执行
int executeStatus;
long beginTime = System.currentTimeMillis();
try {
// 执行注解处方法并返回结果
// 执行成功
executeStatus = 1;
result = point.proceed();
} catch (Throwable throwable) {
// 将异常信息包装返回
// 执行失败
executeStatus = 0;
System.err.println(throwable.getMessage());
result = RespResult.error(throwable.getMessage());
}
// 计算执行时长(毫秒)
long time = System.currentTimeMillis() - beginTime;
// 保存日志
saveLog(point, time, result, executeStatus);
// 返回执行结果
return result;
}
/**
* 注解处方法执行结果-再保存日志
*
* @param joinPoint
* @param time
* @param result
*/
private void saveLog(ProceedingJoinPoint joinPoint, long time, Object result, int executeStatus) {
// 获取HttpServletRequest请求对象
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
// 从切面织入点处通过反射机制获取织入点处的方法
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
// 获取切入点所在的方法
Method method = signature.getMethod();
// 获取操作
Log logAnnotation = method.getAnnotation(Log.class);
UserLog userLog = new UserLog();
String token = request.getHeader(LOGIN_TOKEN_KEY);
if (StringUtils.isNotBlank(token)) {
String userId = JwtUtil.getUserId(token);
userLog.setUserId(Integer.valueOf(userId));
}
// 模块名称
userLog.setModelName(joinPoint.getTarget().getClass().getName());
// 请求的方法参数值
Object[] args = joinPoint.getArgs();
// 请求的方法参数名称 局部变量表参数名称发现器
LocalVariableTableParameterNameDiscoverer localVariableTableParameterNameDiscoverer = new LocalVariableTableParameterNameDiscoverer();
// 请求方式:["request","body"]
String[] paramNames = localVariableTableParameterNameDiscoverer.getParameterNames(method);
try{
String paramNamesStr = new ObjectMapper().writeValueAsString(paramNames);
String argsStr = new ObjectMapper().writeValueAsString(args);
// 设置原始请求参数
userLog.setOriginalParams(paramNamesStr + " - " + argsStr);
} catch(IOException e){
log.error(e.getMessage());
}
if (args != null && paramNames != null) {
String params = "";
for (int i = 0; i < args.length; i++) {
params += " " + paramNames[i] + ":" + args[i];
}
// 设置处理后的请求参数
userLog.setParams(params.trim());
}
// 操作名称
userLog.setActionName(signature.getName() + "()");
// 请求地址
userLog.setRequestUrl(request.getRequestURL().toString());
// 接口描述
userLog.setDescription(logAnnotation.description());
// 设置IP地址
userLog.setIp(IpUtil.getIpAddr(request));
userLog.setExecuteTime((double) time);
// 请求结果
try {
// 请求的结果
String resultStr = new ObjectMapper().writeValueAsString(result);
userLog.setResponseResult(resultStr);
} catch (IOException e) {
System.err.println(e);
}
userLog.setExecuteStatus(executeStatus);
// 保存系统日志
userLogMapper.insert(userLog);
}
}