IDEA+连接数据库+Easy Code逆向工程

 

1、在IDEA界面选择选择如下

IDEA+连接数据库+Easy Code逆向工程_第1张图片

2、配置数据库驱动

IDEA+连接数据库+Easy Code逆向工程_第2张图片

3、配置数据库账户和URL信息

IDEA+连接数据库+Easy Code逆向工程_第3张图片

URL说明(只需要修改数据库地址和库名即可):jdbc:mysql://localhost:3306/dolabor?useUnicode=true&characterEncoding=UTF-8&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=UTC

4、连接数据库成功,右击选择数据库需要使用的库、表

IDEA+连接数据库+Easy Code逆向工程_第4张图片

5、搜索插件EasyCode数据库逆向插件

IDEA+连接数据库+Easy Code逆向工程_第5张图片

6、修改EasyCode的插件模板去除表名前缀

IDEA+连接数据库+Easy Code逆向工程_第6张图片

7、将需要的模板加上去前缀代码即可(内容如下)

## 去掉t_表前缀
$!init

IDEA+连接数据库+Easy Code逆向工程_第7张图片

8、由于当前下载插件带的service模板存在异常故修改备份于此(修改成自己开发习惯)

 注意去表头配置:


##去掉表的t_前缀
$!tableInfo.setName($tool.getClassName($tableInfo.obj.name.replaceFirst("t_","")))

 图片如下:

IDEA+连接数据库+Easy Code逆向工程_第8张图片

 

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、选择对应的表文件右击创建所需的文件

IDEA+连接数据库+Easy Code逆向工程_第9张图片

10、在弹出的对话框操作即可

IDEA+连接数据库+Easy Code逆向工程_第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")

TkBaseMapper基类:

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 {
}

ResponseModel统一返回类:



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;
    }
}

ResponseHelper统一返回类:



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);
    }
}

ResultCode枚举类:


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;
    }
}

userId注解:

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 {
}

webMvc配置:


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(Class2) 判定此 Class1 对象所表示的类或接口与指定的 Class2 参数所表示的类或接口是否相同,或是否是其超类或超接口。如果是则返回 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 {

    /**
     * 重写的这两个方法是用来在controller将数据进行返回前进行增强操作,
     * supports方法要返回为true才会执行beforeBodyWrite方法,
     * 所以如果有些情况不需要进行增强操作可以在supports方法里进行判断。
     * 对返回数据进行真正的操作还是在beforeBodyWrite方法中,
     * 我们可以直接在该方法里包装数据,这样就不需要每个接口都进行数据包装
     * 错误情况可包装,正常返回不用包装
     */

    @Override
    public boolean supports(MethodParameter methodParameter, Class> aClass) {
        // 如果接口返回的类型本身就是 ResponseModel 那就没有必要进行额外的操作,返回false
        boolean result = methodParameter.getGenericParameterType().equals(ResponseModel.class);
        return !result;
    }

    @Override
    public Object beforeBodyWrite(Object o, MethodParameter methodParameter, MediaType mediaType, Class> aClass, ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse) {

        // String类型不能直接包装,所以要进行些特别的处理
        if (methodParameter.getGenericParameterType().equals(String.class)) {
            ObjectMapper objectMapper = new ObjectMapper();
            try {
                // 将数据包装在ResultVO里后,再转换为json字符串响应给前端
                return objectMapper.writeValueAsString(new ResponseModel<>(o));
            } catch (JsonProcessingException e) {

                throw new ApiException("返回String类型错误");
            }
        }

        // 将原本的数据包装在ResultVO里
        return new ResponseModel<>(o);
    }
}
 
  

API异常处理:



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;
    }
}

log切面日志




import java.lang.annotation.*;

/**
 * 在Controller方法上加入改注解会自动记录日志
 *
 * @author pc
 */
@Documented
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Log {

    /**
     * 描述. 执行
     */
    String description() default "";
}

Log切面注解实现类



/**
 * 日志方面
 *
 * @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);
    }
}

 

你可能感兴趣的:(Java)