初始化提交
This commit is contained in:
25
common/core/.gitignore
vendored
Normal file
25
common/core/.gitignore
vendored
Normal file
@ -0,0 +1,25 @@
|
||||
/target/
|
||||
!.mvn/wrapper/maven-wrapper.jar
|
||||
|
||||
### STS ###
|
||||
.apt_generated
|
||||
.classpath
|
||||
.factorypath
|
||||
.project
|
||||
.settings
|
||||
.springBeans
|
||||
.sts4-cache
|
||||
|
||||
### IntelliJ IDEA ###
|
||||
.idea
|
||||
*.iws
|
||||
*.iml
|
||||
*.ipr
|
||||
|
||||
### NetBeans ###
|
||||
/nbproject/private/
|
||||
/build/
|
||||
/nbbuild/
|
||||
/dist/
|
||||
/nbdist/
|
||||
/.nb-gradle/
|
||||
40
common/core/pom.xml
Normal file
40
common/core/pom.xml
Normal file
@ -0,0 +1,40 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>business.chaoran</groupId>
|
||||
<artifactId>core</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>core</name>
|
||||
<description>Demo Core project for Spring Boot</description>
|
||||
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
|
||||
<maven.compiler.source>1.8</maven.compiler.source>
|
||||
<maven.compiler.target>1.8</maven.compiler.target>
|
||||
</properties>
|
||||
|
||||
<parent>
|
||||
<groupId>business.chaoran</groupId>
|
||||
<artifactId>common</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<dependencies>
|
||||
<!--Swagger2 - RESTful API文档-->
|
||||
<dependency>
|
||||
<groupId>io.springfox</groupId>
|
||||
<artifactId>springfox-swagger2</artifactId>
|
||||
<version>2.9.2</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.springfox</groupId>
|
||||
<artifactId>springfox-swagger-ui</artifactId>
|
||||
<version>2.9.2</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
@ -0,0 +1,167 @@
|
||||
package com.springboot.cloud.common.core.entity.vo;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
import com.springboot.cloud.common.core.exception.BaseException;
|
||||
import com.springboot.cloud.common.core.exception.ErrorType;
|
||||
import com.springboot.cloud.common.core.exception.SystemErrorType;
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Getter;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.time.ZonedDateTime;
|
||||
|
||||
@ApiModel(description = "rest请求的返回模型,所有rest正常都返回该类的对象")
|
||||
@Getter
|
||||
public class Result<T> {
|
||||
|
||||
public static final String SUCCESSFUL_CODE = "000000";
|
||||
public static final String SUCCESSFUL_MESG = "处理成功";
|
||||
|
||||
@ApiModelProperty(value = "处理结果code", required = true)
|
||||
private String code;
|
||||
@ApiModelProperty(value = "处理结果描述信息")
|
||||
private String msg;
|
||||
@ApiModelProperty(value = "请求结果生成时间戳")
|
||||
private Instant time;
|
||||
@ApiModelProperty(value = "处理结果数据信息")
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
private T data;
|
||||
|
||||
public Result() {
|
||||
this.time = ZonedDateTime.now().toInstant();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param errorType
|
||||
*/
|
||||
public Result(ErrorType errorType) {
|
||||
this.code = errorType.getCode();
|
||||
this.msg = errorType.getMesg();
|
||||
this.time = ZonedDateTime.now().toInstant();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param errorType
|
||||
* @param data
|
||||
*/
|
||||
public Result(ErrorType errorType, T data) {
|
||||
this(errorType);
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
/**
|
||||
* 内部使用,用于构造成功的结果
|
||||
*
|
||||
* @param code
|
||||
* @param msg
|
||||
* @param data
|
||||
*/
|
||||
private Result(String code, String msg, T data) {
|
||||
this.code = code;
|
||||
this.msg = msg;
|
||||
this.data = data;
|
||||
this.time = ZonedDateTime.now().toInstant();
|
||||
}
|
||||
|
||||
/**
|
||||
* 快速创建成功结果并返回结果数据
|
||||
*
|
||||
* @param data
|
||||
* @return Result
|
||||
*/
|
||||
public static Result success(Object data) {
|
||||
return new Result<>(SUCCESSFUL_CODE, SUCCESSFUL_MESG, data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 快速创建成功结果
|
||||
*
|
||||
* @return Result
|
||||
*/
|
||||
public static Result success() {
|
||||
return success(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 系统异常类没有返回数据
|
||||
*
|
||||
* @return Result
|
||||
*/
|
||||
public static Result fail() {
|
||||
return new Result(SystemErrorType.SYSTEM_ERROR);
|
||||
}
|
||||
|
||||
/**
|
||||
* 系统异常类没有返回数据
|
||||
*
|
||||
* @param baseException
|
||||
* @return Result
|
||||
*/
|
||||
public static Result fail(BaseException baseException) {
|
||||
return fail(baseException, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 系统异常类并返回结果数据
|
||||
*
|
||||
* @param data
|
||||
* @return Result
|
||||
*/
|
||||
public static Result fail(BaseException baseException, Object data) {
|
||||
return new Result<>(baseException.getErrorType(), data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 系统异常类并返回结果数据
|
||||
*
|
||||
* @param errorType
|
||||
* @param data
|
||||
* @return Result
|
||||
*/
|
||||
public static Result fail(ErrorType errorType, Object data) {
|
||||
return new Result<>(errorType, data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 系统异常类并返回结果数据
|
||||
*
|
||||
* @param errorType
|
||||
* @return Result
|
||||
*/
|
||||
public static Result fail(ErrorType errorType) {
|
||||
return Result.fail(errorType, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 系统异常类并返回结果数据
|
||||
*
|
||||
* @param data
|
||||
* @return Result
|
||||
*/
|
||||
public static Result fail(Object data) {
|
||||
return new Result<>(SystemErrorType.SYSTEM_ERROR, data);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 成功code=000000
|
||||
*
|
||||
* @return true/false
|
||||
*/
|
||||
@JsonIgnore
|
||||
public boolean isSuccess() {
|
||||
return SUCCESSFUL_CODE.equals(this.code);
|
||||
}
|
||||
|
||||
/**
|
||||
* 失败
|
||||
*
|
||||
* @return true/false
|
||||
*/
|
||||
@JsonIgnore
|
||||
public boolean isFail() {
|
||||
return !isSuccess();
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,32 @@
|
||||
package com.springboot.cloud.common.core.exception;
|
||||
|
||||
import lombok.Getter;
|
||||
|
||||
@Getter
|
||||
public class BaseException extends RuntimeException {
|
||||
/**
|
||||
* 异常对应的错误类型
|
||||
*/
|
||||
private final ErrorType errorType;
|
||||
|
||||
/**
|
||||
* 默认是系统异常
|
||||
*/
|
||||
public BaseException() {
|
||||
this.errorType = SystemErrorType.SYSTEM_ERROR;
|
||||
}
|
||||
|
||||
public BaseException(ErrorType errorType) {
|
||||
this.errorType = errorType;
|
||||
}
|
||||
|
||||
public BaseException(ErrorType errorType, String message) {
|
||||
super(message);
|
||||
this.errorType = errorType;
|
||||
}
|
||||
|
||||
public BaseException(ErrorType errorType, String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
this.errorType = errorType;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,17 @@
|
||||
package com.springboot.cloud.common.core.exception;
|
||||
|
||||
public interface ErrorType {
|
||||
/**
|
||||
* 返回code
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
String getCode();
|
||||
|
||||
/**
|
||||
* 返回mesg
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
String getMesg();
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
package com.springboot.cloud.common.core.exception;
|
||||
|
||||
/**
|
||||
* Created by zhoutaoo on 2018/6/2.
|
||||
*/
|
||||
public class ServiceException extends BaseException {
|
||||
|
||||
//TODO 对业务异常的返回码进行校验,规范到一定范围内
|
||||
|
||||
|
||||
}
|
||||
@ -0,0 +1,34 @@
|
||||
package com.springboot.cloud.common.core.exception;
|
||||
|
||||
import lombok.Getter;
|
||||
|
||||
@Getter
|
||||
public enum SystemErrorType implements ErrorType {
|
||||
|
||||
SYSTEM_ERROR("-1", "系统异常"),
|
||||
SYSTEM_BUSY("000001", "系统繁忙,请稍候再试"),
|
||||
|
||||
GATEWAY_NOT_FOUND_SERVICE("010404", "服务未找到"),
|
||||
GATEWAY_ERROR("010500", "网关异常"),
|
||||
GATEWAY_CONNECT_TIME_OUT("010002", "网关超时"),
|
||||
|
||||
ARGUMENT_NOT_VALID("020000", "请求参数校验不通过"),
|
||||
INVALID_TOKEN("020001", "无效token"),
|
||||
UPLOAD_FILE_SIZE_LIMIT("020010", "上传文件大小超过限制"),
|
||||
|
||||
DUPLICATE_PRIMARY_KEY("030000","唯一键冲突");
|
||||
|
||||
/**
|
||||
* 错误类型码
|
||||
*/
|
||||
private String code;
|
||||
/**
|
||||
* 错误类型描述信息
|
||||
*/
|
||||
private String mesg;
|
||||
|
||||
SystemErrorType(String code, String mesg) {
|
||||
this.code = code;
|
||||
this.mesg = mesg;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,84 @@
|
||||
package com.springboot.cloud.common.core.util;
|
||||
|
||||
import com.google.common.collect.Maps;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* {"companies":[{"default":true,"authority":"1"},{"default":false,"authority":"2"}],"user_name":"admin","scope":["read"],"exp":1610100088,"authorities":["1","2"],"jti":"nt9bTYbUe8IzuEgfAz70nwaMveI","client_id":"test_client"}
|
||||
*/
|
||||
|
||||
/**
|
||||
* 用户上下文
|
||||
*/
|
||||
public class UserContextHolder {
|
||||
|
||||
private ThreadLocal<Map<String, String>> threadLocal;
|
||||
|
||||
private UserContextHolder() {
|
||||
this.threadLocal = new ThreadLocal<>();
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建实例
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public static UserContextHolder getInstance() {
|
||||
return SingletonHolder.sInstance;
|
||||
}
|
||||
|
||||
/**
|
||||
* 静态内部类单例模式
|
||||
* 单例初使化
|
||||
*/
|
||||
private static class SingletonHolder {
|
||||
private static final UserContextHolder sInstance = new UserContextHolder();
|
||||
}
|
||||
|
||||
/**
|
||||
* 用户上下文中放入信息
|
||||
*
|
||||
* @param map
|
||||
*/
|
||||
public void setContext(Map<String, String> map) {
|
||||
threadLocal.set(map);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取上下文中的信息
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public Map<String, String> getContext() {
|
||||
return threadLocal.get();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取上下文中的用户名
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public String getUsername() {
|
||||
return Optional.ofNullable(threadLocal.get()).orElse(Maps.newHashMap()).get("user_name");
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取上下文中用户登录的公司
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public String getCurrentCompany() {
|
||||
return Optional.ofNullable(threadLocal.get()).orElse(Maps.newHashMap()).get("company");
|
||||
}
|
||||
|
||||
/**
|
||||
* 清空上下文
|
||||
*/
|
||||
public void clear() {
|
||||
threadLocal.remove();
|
||||
}
|
||||
|
||||
}
|
||||
46
common/pom.xml
Normal file
46
common/pom.xml
Normal file
@ -0,0 +1,46 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>business.chaoran</groupId>
|
||||
<artifactId>common</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
<packaging>pom</packaging>
|
||||
|
||||
<name>common</name>
|
||||
<description>Demo Common project for Spring Boot</description>
|
||||
|
||||
<modules>
|
||||
<module>core</module>
|
||||
<module>web</module>
|
||||
</modules>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>commons-lang</groupId>
|
||||
<artifactId>commons-lang</artifactId>
|
||||
<version>2.6</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-core</artifactId>
|
||||
<version>5.0.11.RELEASE</version>
|
||||
</dependency>
|
||||
<!--使用 lombok 简化 Java 代码-->
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
<version>1.18.10</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<!--测试-->
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<version>4.12</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
102
common/web/pom.xml
Normal file
102
common/web/pom.xml
Normal file
@ -0,0 +1,102 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>business.chaoran</groupId>
|
||||
<artifactId>web</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>web</name>
|
||||
<description>Demo Web project for Spring Boot</description>
|
||||
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
|
||||
<maven.compiler.source>1.8</maven.compiler.source>
|
||||
<maven.compiler.target>1.8</maven.compiler.target>
|
||||
</properties>
|
||||
|
||||
<parent>
|
||||
<groupId>business.chaoran</groupId>
|
||||
<artifactId>common</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>business.chaoran</groupId>
|
||||
<artifactId>core</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<!--spring web相关包-->
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-web</artifactId>
|
||||
<version>5.0.4.RELEASE</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-webmvc</artifactId>
|
||||
<version>5.1.0.RELEASE</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-databind</artifactId>
|
||||
<version>2.10.0.pr1</version>
|
||||
</dependency>
|
||||
<!--mybatis plus依赖包-->
|
||||
<dependency>
|
||||
<groupId>com.baomidou</groupId>
|
||||
<artifactId>mybatis-plus-boot-starter</artifactId>
|
||||
<version>3.1.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.mybatis</groupId>
|
||||
<artifactId>mybatis-spring</artifactId>
|
||||
<version>2.0.0</version>
|
||||
</dependency>
|
||||
<!--Redis缓存-->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-data-redis</artifactId>
|
||||
<version>2.1.4.RELEASE</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-pool2</artifactId>
|
||||
<version>2.6.0</version>
|
||||
</dependency>
|
||||
<!--开发相关-->
|
||||
<dependency>
|
||||
<groupId>javax.servlet</groupId>
|
||||
<artifactId>javax.servlet-api</artifactId>
|
||||
<version>3.1.0</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<!--测试框架-->
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-test</artifactId>
|
||||
<version>5.1.6.RELEASE</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
<scope>test</scope>
|
||||
<version>RELEASE</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.mybatis</groupId>
|
||||
<artifactId>mybatis</artifactId>
|
||||
<version>3.5.1</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.github.openfeign</groupId>
|
||||
<artifactId>feign-core</artifactId>
|
||||
<version>10.1.0</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
@ -0,0 +1,43 @@
|
||||
package com.springboot.cloud.common.web.entity.form;
|
||||
|
||||
import com.springboot.cloud.common.web.entity.po.BasePo;
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import lombok.Data;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
|
||||
@ApiModel
|
||||
@Slf4j
|
||||
@Data
|
||||
public class BaseForm<T extends BasePo> {
|
||||
/**
|
||||
* 用户名
|
||||
*/
|
||||
private String username;
|
||||
|
||||
/**
|
||||
* Form转化为Po,进行后续业务处理
|
||||
*
|
||||
* @param clazz
|
||||
* @return
|
||||
*/
|
||||
public T toPo(Class<T> clazz) {
|
||||
T t = BeanUtils.instantiateClass(clazz);
|
||||
BeanUtils.copyProperties(this, t);
|
||||
return t;
|
||||
}
|
||||
|
||||
/**
|
||||
* Form转化为Po,进行后续业务处理
|
||||
*
|
||||
* @param id
|
||||
* @param clazz
|
||||
* @return
|
||||
*/
|
||||
public T toPo(String id, Class<T> clazz) {
|
||||
T t = BeanUtils.instantiateClass(clazz);
|
||||
t.setId(id);
|
||||
BeanUtils.copyProperties(this, t);
|
||||
return t;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,44 @@
|
||||
package com.springboot.cloud.common.web.entity.form;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.springboot.cloud.common.web.entity.param.BaseParam;
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import lombok.Data;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
|
||||
@ApiModel
|
||||
@Slf4j
|
||||
@Data
|
||||
public class BaseQueryForm<P extends BaseParam> extends BaseForm {
|
||||
/**
|
||||
* 分页查询的参数,当前页数
|
||||
*/
|
||||
private long current = 1;
|
||||
/**
|
||||
* 分页查询的参数,当前页面每页显示的数量
|
||||
*/
|
||||
private long size = 10;
|
||||
|
||||
/**
|
||||
* Form转化为Param
|
||||
*
|
||||
* @param clazz
|
||||
* @return
|
||||
*/
|
||||
public P toParam(Class<P> clazz) {
|
||||
P p = BeanUtils.instantiateClass(clazz);
|
||||
BeanUtils.copyProperties(this, p);
|
||||
return p;
|
||||
}
|
||||
|
||||
/**
|
||||
* 从form中获取page参数,用于分页查询参数
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public Page getPage() {
|
||||
return new Page(this.getCurrent(), this.getSize());
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,21 @@
|
||||
package com.springboot.cloud.common.web.entity.param;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.springboot.cloud.common.web.entity.po.BasePo;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
|
||||
@Data
|
||||
public class BaseParam<T extends BasePo> {
|
||||
private Date createdTimeStart;
|
||||
private Date createdTimeEnd;
|
||||
|
||||
public QueryWrapper<T> build() {
|
||||
QueryWrapper<T> queryWrapper = new QueryWrapper<>();
|
||||
queryWrapper.ge(null != this.createdTimeStart, "created_time", this.createdTimeStart)
|
||||
.le(null != this.createdTimeEnd, "created_time", this.createdTimeEnd);
|
||||
return queryWrapper;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,29 @@
|
||||
package com.springboot.cloud.common.web.entity.po;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.FieldFill;
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
@Data
|
||||
public class BasePo implements Serializable {
|
||||
public final static String DEFAULT_USERNAME = "system";
|
||||
@TableId(type = IdType.ID_WORKER_STR)
|
||||
private String id;
|
||||
|
||||
@TableField(fill = FieldFill.INSERT)
|
||||
private String createdBy;
|
||||
|
||||
@TableField(fill = FieldFill.INSERT)
|
||||
private Date createdTime;
|
||||
|
||||
@TableField(fill = FieldFill.INSERT_UPDATE)
|
||||
private String updatedBy;
|
||||
|
||||
@TableField(fill = FieldFill.INSERT_UPDATE)
|
||||
private Date updatedTime;
|
||||
}
|
||||
@ -0,0 +1,13 @@
|
||||
package com.springboot.cloud.common.web.entity.vo;
|
||||
|
||||
import com.springboot.cloud.common.web.entity.po.BasePo;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
public class BaseVo<T extends BasePo> implements Serializable {
|
||||
private String id;
|
||||
}
|
||||
@ -0,0 +1,59 @@
|
||||
package com.springboot.cloud.common.web.exception;
|
||||
|
||||
import com.springboot.cloud.common.core.entity.vo.Result;
|
||||
import com.springboot.cloud.common.core.exception.BaseException;
|
||||
import com.springboot.cloud.common.core.exception.SystemErrorType;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.dao.DuplicateKeyException;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.web.bind.MethodArgumentNotValidException;
|
||||
import org.springframework.web.bind.MissingServletRequestParameterException;
|
||||
import org.springframework.web.bind.annotation.ExceptionHandler;
|
||||
import org.springframework.web.bind.annotation.ResponseStatus;
|
||||
import org.springframework.web.multipart.MultipartException;
|
||||
|
||||
@Slf4j
|
||||
public class DefaultGlobalExceptionHandlerAdvice {
|
||||
|
||||
@ExceptionHandler(value = {MissingServletRequestParameterException.class})
|
||||
public Result missingServletRequestParameterException(MissingServletRequestParameterException ex) {
|
||||
log.error("missing servlet request parameter exception:{}", ex.getMessage());
|
||||
return Result.fail(SystemErrorType.ARGUMENT_NOT_VALID);
|
||||
}
|
||||
|
||||
@ExceptionHandler(value = {MultipartException.class})
|
||||
public Result uploadFileLimitException(MultipartException ex) {
|
||||
log.error("upload file size limit:{}", ex.getMessage());
|
||||
return Result.fail(SystemErrorType.UPLOAD_FILE_SIZE_LIMIT);
|
||||
}
|
||||
|
||||
@ExceptionHandler(value = {MethodArgumentNotValidException.class})
|
||||
public Result serviceException(MethodArgumentNotValidException ex) {
|
||||
log.error("service exception:{}", ex.getMessage());
|
||||
return Result.fail(SystemErrorType.ARGUMENT_NOT_VALID, ex.getBindingResult().getFieldError().getDefaultMessage());
|
||||
}
|
||||
|
||||
@ExceptionHandler(value = {DuplicateKeyException.class})
|
||||
public Result duplicateKeyException(DuplicateKeyException ex) {
|
||||
log.error("primary key duplication exception:{}", ex.getMessage());
|
||||
return Result.fail(SystemErrorType.DUPLICATE_PRIMARY_KEY);
|
||||
}
|
||||
|
||||
@ExceptionHandler(value = {BaseException.class})
|
||||
public Result baseException(BaseException ex) {
|
||||
log.error("base exception:{}", ex.getMessage());
|
||||
return Result.fail(ex.getErrorType());
|
||||
}
|
||||
|
||||
@ExceptionHandler(value = {Exception.class})
|
||||
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
|
||||
public Result exception() {
|
||||
return Result.fail();
|
||||
}
|
||||
|
||||
@ExceptionHandler(value = {Throwable.class})
|
||||
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
|
||||
public Result throwable() {
|
||||
return Result.fail();
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,36 @@
|
||||
package com.springboot.cloud.common.web.handler;
|
||||
|
||||
import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
|
||||
import com.springboot.cloud.common.core.util.UserContextHolder;
|
||||
import com.springboot.cloud.common.web.entity.po.BasePo;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.apache.ibatis.reflection.MetaObject;
|
||||
|
||||
import java.time.ZonedDateTime;
|
||||
import java.util.Date;
|
||||
|
||||
@Slf4j
|
||||
public class PoMetaObjectHandler implements MetaObjectHandler {
|
||||
/**
|
||||
* 获取当前访问用户,为空返回默认system
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
private String getCurrentUsername() {
|
||||
return StringUtils.defaultIfBlank(UserContextHolder.getInstance().getUsername(), BasePo.DEFAULT_USERNAME);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void insertFill(MetaObject metaObject) {
|
||||
this.setInsertFieldValByName("createdBy", getCurrentUsername(), metaObject);
|
||||
this.setInsertFieldValByName("createdTime", Date.from(ZonedDateTime.now().toInstant()), metaObject);
|
||||
this.updateFill(metaObject);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateFill(MetaObject metaObject) {
|
||||
this.setUpdateFieldValByName("updatedBy", getCurrentUsername(), metaObject);
|
||||
this.setUpdateFieldValByName("updatedTime", Date.from(ZonedDateTime.now().toInstant()), metaObject);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,46 @@
|
||||
package com.springboot.cloud.common.web.interceptor;
|
||||
|
||||
/*
|
||||
**********************************************
|
||||
* DATE PERSON REASON
|
||||
* 2020-12-04 FXY Created
|
||||
**********************************************
|
||||
*/
|
||||
|
||||
|
||||
import feign.RequestInterceptor;
|
||||
import feign.RequestTemplate;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.util.DigestUtils;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
|
||||
|
||||
@Slf4j
|
||||
public class FeignBasicAuthRequestInterceptor implements RequestInterceptor {
|
||||
|
||||
public FeignBasicAuthRequestInterceptor(){
|
||||
log.info("========================加载自定义拦截器=========================");
|
||||
}
|
||||
|
||||
//服务间调用头
|
||||
private static final String SERVER_CLIENT_TOKEN="server-client-token";
|
||||
//服务间调用秘钥
|
||||
private static final String SERVER_CLIENT_SECRET="server";
|
||||
//网关调用服务头
|
||||
private static final String X_CLIENT_TOKEN="x-client-token";
|
||||
|
||||
@Override
|
||||
public void apply(RequestTemplate requestTemplate) {
|
||||
String url = requestTemplate.path();
|
||||
Map<String, Collection<String>> headers = requestTemplate.headers();
|
||||
if(!headers.containsKey(X_CLIENT_TOKEN)){
|
||||
String method = requestTemplate.method();
|
||||
String originStr = new StringBuilder().append(url).append(method).append(SERVER_CLIENT_TOKEN).append(SERVER_CLIENT_SECRET).toString();
|
||||
// 加入自定义头信息
|
||||
String md5Secret = DigestUtils.md5DigestAsHex(originStr.getBytes());
|
||||
requestTemplate.header(SERVER_CLIENT_TOKEN, md5Secret);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,87 @@
|
||||
package com.springboot.cloud.common.web.interceptor;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.springboot.cloud.common.core.util.UserContextHolder;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.DigestUtils;
|
||||
import org.springframework.web.servlet.HandlerInterceptor;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* 用户信息拦截器
|
||||
*/
|
||||
@Slf4j
|
||||
public class UserInterceptor implements HandlerInterceptor {
|
||||
/**
|
||||
* 服务间调用token用户信息,格式为json
|
||||
* {
|
||||
* "user_name":"必须有"
|
||||
* "自定义key:"value"
|
||||
* }
|
||||
*/
|
||||
//获取相关授权信息请求头
|
||||
private static final String X_CLIENT_TOKEN_USER = "x-client-token-user";
|
||||
|
||||
//网关调用服务请求头
|
||||
private static final String X_CLIENT_TOKEN = "x-client-token";
|
||||
|
||||
//网关调用服务秘钥
|
||||
private static final String X_CLIENT_SECRET = "gateway-web";
|
||||
|
||||
//服务间调用请求头
|
||||
private static final String SERVER_CLIENT_TOKEN = "server-client-token";
|
||||
|
||||
//服务间调用秘钥
|
||||
private static final String SERVER_CLIENT_SECRET = "server";
|
||||
|
||||
//当前用户登录公司
|
||||
private static final String USER_CURRENT_COMPANY = "company";
|
||||
|
||||
|
||||
@Override
|
||||
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
|
||||
//从网关获取并校验,通过校验就可信任x-client-token-user中的信息
|
||||
boolean b = checkToken(request);
|
||||
if (!b) {
|
||||
//重定向到登录前端
|
||||
response.sendRedirect("https://www.baidu.com");
|
||||
return b;
|
||||
}
|
||||
|
||||
//放入上下文数据
|
||||
String userInfoString = StringUtils.defaultIfBlank(request.getHeader(X_CLIENT_TOKEN_USER), "{}");
|
||||
Map context = new ObjectMapper().readValue(userInfoString, Map.class);
|
||||
context.put("company", request.getHeader(USER_CURRENT_COMPANY));
|
||||
UserContextHolder.getInstance().setContext(context);
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean checkToken(HttpServletRequest request) {
|
||||
String method = request.getMethod();
|
||||
String url = request.getServletPath();
|
||||
Optional<String> serverToken = Optional.ofNullable(request.getHeader(SERVER_CLIENT_TOKEN));
|
||||
Optional<String> clientToken = Optional.ofNullable(request.getHeader(X_CLIENT_TOKEN));
|
||||
if (serverToken.isPresent()) {
|
||||
//如果是服务间相互调用不需要加contextPath,因为feign拦截器中加密是根据servletPath来加密的,此处也是根据servletPath解密的
|
||||
String originStr = new StringBuilder().append(url).append(method).append(SERVER_CLIENT_TOKEN).append(SERVER_CLIENT_SECRET).toString();
|
||||
return DigestUtils.md5DigestAsHex(originStr.getBytes()).equals(serverToken.get());
|
||||
} else if (clientToken.isPresent()) {
|
||||
//如果是网关调用服务,网关服务需要加上contextPath
|
||||
String originStr = new StringBuilder().append(request.getContextPath().concat(url)).append(method).append(X_CLIENT_TOKEN).append(X_CLIENT_SECRET).toString();
|
||||
return DigestUtils.md5DigestAsHex(originStr.getBytes()).equals(clientToken.get());
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception {
|
||||
UserContextHolder.getInstance().clear();
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,48 @@
|
||||
package com.springboot.cloud.common.web.redis;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonAutoDetect;
|
||||
import com.fasterxml.jackson.annotation.PropertyAccessor;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import org.springframework.cache.CacheManager;
|
||||
import org.springframework.cache.annotation.CachingConfigurerSupport;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.data.redis.cache.RedisCacheConfiguration;
|
||||
import org.springframework.data.redis.cache.RedisCacheManager;
|
||||
import org.springframework.data.redis.cache.RedisCacheWriter;
|
||||
import org.springframework.data.redis.connection.RedisConnectionFactory;
|
||||
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
|
||||
import org.springframework.data.redis.serializer.RedisSerializationContext;
|
||||
|
||||
import java.time.Duration;
|
||||
|
||||
@Configuration
|
||||
public class RedisConfig extends CachingConfigurerSupport {
|
||||
|
||||
@Bean
|
||||
public CacheManager cacheManager(RedisConnectionFactory factory) {
|
||||
//对象的序列化
|
||||
RedisSerializationContext.SerializationPair valueSerializationPair
|
||||
= RedisSerializationContext.SerializationPair.fromSerializer(jackson2JsonRedisSerializer());
|
||||
//全局redis缓存过期时间
|
||||
RedisCacheConfiguration redisCacheConfiguration = RedisCacheConfiguration.defaultCacheConfig()
|
||||
.entryTtl(Duration.ofDays(1))
|
||||
// .serializeKeysWith()
|
||||
.serializeValuesWith(valueSerializationPair);
|
||||
|
||||
return new RedisCacheManager(RedisCacheWriter.nonLockingRedisCacheWriter(factory), redisCacheConfiguration);
|
||||
}
|
||||
|
||||
private Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer() {
|
||||
Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class);
|
||||
jackson2JsonRedisSerializer.setObjectMapper(objectMapper());
|
||||
return jackson2JsonRedisSerializer;
|
||||
}
|
||||
|
||||
private ObjectMapper objectMapper() {
|
||||
ObjectMapper objectMapper = new ObjectMapper();
|
||||
objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
|
||||
objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
|
||||
return objectMapper;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,12 @@
|
||||
package com.springboot.cloud.common.web.exception;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
public class DefaultGlobalExceptionHandlerAdviceTest {
|
||||
|
||||
@Test
|
||||
public void testMethod() {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,27 @@
|
||||
package com.springboot.cloud.common.web.interceptor;
|
||||
|
||||
import com.springboot.cloud.common.core.util.UserContextHolder;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
import org.springframework.mock.web.MockHttpServletResponse;
|
||||
|
||||
public class UserInterceptorTest {
|
||||
@Test
|
||||
public void preHandle_当未设置token_user_那么正常处理下一个handle() throws Exception {
|
||||
UserInterceptor userInterceptor = new UserInterceptor();
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
userInterceptor.preHandle(request, response, new Object());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void preHandle_当设置token的username_那么username可以在线程中拿出来用() throws Exception {
|
||||
UserInterceptor userInterceptor = new UserInterceptor();
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.addHeader("x-client-token-user", "{\"user_name\":\"zhangsan\"}");
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
userInterceptor.preHandle(request, response, new Object());
|
||||
Assert.assertEquals(UserContextHolder.getInstance().getUsername(), "zhangsan");
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user