Initial commit

This commit is contained in:
曾文豪
2022-12-22 17:25:10 +08:00
commit 7cec4f3f35
61 changed files with 3696 additions and 0 deletions

View File

@@ -0,0 +1,13 @@
package com.tiesheng.core;
import org.springframework.context.annotation.ComponentScan;
/**
* @author hao
*/
@ComponentScan({
"com.tiesheng.core.**.*",
})
public class CoreAutoImportSelector {
}

View File

@@ -0,0 +1,19 @@
package com.tiesheng.core;
import com.tiesheng.migration.MigrationAutoImportSelector;
import org.springframework.context.annotation.Import;
import java.lang.annotation.*;
/**
* @author hao
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
@Documented
@Import({
CoreAutoImportSelector.class,
MigrationAutoImportSelector.class
})
public @interface EnableTieshengWeb {
}

View File

@@ -0,0 +1,78 @@
package com.tiesheng.core.config.exception;
import cn.hutool.core.exceptions.ValidateException;
import cn.hutool.extra.spring.SpringUtil;
import cn.hutool.log.LogFactory;
import com.tiesheng.util.exception.ApiException;
import com.tiesheng.util.exception.ApiRespEnum;
import com.tiesheng.util.pojos.ApiResp;
import org.springframework.boot.autoconfigure.web.servlet.MultipartProperties;
import org.springframework.validation.BindException;
import org.springframework.validation.FieldError;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException;
import org.springframework.web.multipart.MaxUploadSizeExceededException;
import org.springframework.web.servlet.NoHandlerFoundException;
import java.io.IOException;
/**
* @author huang
*/
@RestControllerAdvice
public class SpringExceptionHandler {
/**
* 全局异常捕获
*
* @param e
* @return
*/
@ExceptionHandler(Exception.class)
public ApiResp<String> handle(Exception e) {
// 自定义异常
if (e instanceof ApiException) {
return ((ApiException) e).getApiResp();
}
// 请求异常
if (e instanceof ValidateException) {
return ApiResp.respCust(ApiRespEnum.BadRequest.getCode(), e.getMessage());
}
if (e instanceof BindException) {
FieldError error = ((BindException) e).getFieldError();
String msg = "请求参数不合法";
if (error != null) {
msg = error.getDefaultMessage();
}
return ApiResp.respCust(ApiRespEnum.BadRequest.getCode(), msg);
}
if (e instanceof MethodArgumentTypeMismatchException) {
return ApiResp.respCust(ApiRespEnum.BadRequest.getCode(), "请求参数不合法");
}
if (e instanceof HttpRequestMethodNotSupportedException) {
return ApiResp.respCust(ApiRespEnum.BadRequest.getCode(), "不支持的请求方式");
}
if (e instanceof NoHandlerFoundException) {
return ApiResp.respCust(ApiRespEnum.BadRequest.getCode(), "请求路径不存在");
}
if (e instanceof MaxUploadSizeExceededException) {
MultipartProperties property = SpringUtil.getBean(MultipartProperties.class);
return ApiResp.respCust(ApiRespEnum.BadRequest.getCode(), String.format("上传文件不得超过%dMB", property.getMaxFileSize().toMegabytes()));
}
// 服务器内部异常
if (e instanceof IOException) {
return ApiResp.respCust(ApiRespEnum.ServerError.getCode(), "IO异常");
}
ApiResp<String> apiResp = ApiResp.respCust(ApiRespEnum.ServerError);
LogFactory.get().info(e);
return apiResp;
}
}

View File

@@ -0,0 +1,75 @@
package com.tiesheng.core.config.global;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.spring.SpringUtil;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
/**
* @author hao
*/
@Configuration
@ConfigurationProperties(prefix = "tiesheng.global")
public class GlobalConfig {
private String host;
private String service;
private String version;
///////////////////////////////////////////////////////////////////////////
// 逻辑方法
///////////////////////////////////////////////////////////////////////////
public String getContextPath() {
String context = SpringUtil.getProperty("server.servlet.context-path");
if (StrUtil.isEmpty(context)) {
context = "";
}
return context;
}
/**
* 构建完整的路径
*
* @param path
* @return
*/
public String buildPath(String path) {
if (StrUtil.isEmpty(path)) {
path = "";
}
if (!StrUtil.isEmpty(host) && !StrUtil.startWith(path, "http")) {
path = host + getContextPath() + path;
}
return path;
}
///////////////////////////////////////////////////////////////////////////
// setter\getter
///////////////////////////////////////////////////////////////////////////
public String getHost() {
return host;
}
public void setHost(String host) {
this.host = host;
}
public String getService() {
return service;
}
public void setService(String service) {
this.service = service;
}
public String getVersion() {
return version;
}
public void setVersion(String version) {
this.version = version;
}
}

View File

@@ -0,0 +1,47 @@
package com.tiesheng.core.config.json;
import cn.hutool.log.LogFactory;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.alibaba.fastjson.support.config.FastJsonConfig;
import com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter;
import org.springframework.boot.autoconfigure.http.HttpMessageConverters;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.MediaType;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
/**
* @author hao
*/
@Configuration
public class FastJsonMessageConverter {
/**
* 配置FastJson
*
* @return HttpMessageConverters
*/
@Bean
public HttpMessageConverters fastJsonHttpMessageConverters() {
FastJsonConfig config = new FastJsonConfig();
config.setSerializerFeatures(SerializerFeature.WriteMapNullValue,
SerializerFeature.WriteNullStringAsEmpty,
SerializerFeature.WriteEnumUsingName,
SerializerFeature.WriteNullNumberAsZero);
config.setDateFormat("yyyy-MM-dd HH:mm:ss");
FastJsonHttpMessageConverter fastConverter = new FastJsonHttpMessageConverter();
fastConverter.setFastJsonConfig(config);
fastConverter.setDefaultCharset(StandardCharsets.UTF_8);
List<MediaType> mediaTypes = new ArrayList<>();
mediaTypes.add(MediaType.APPLICATION_JSON);
fastConverter.setSupportedMediaTypes(mediaTypes);
return new HttpMessageConverters(fastConverter);
}
}

View File

@@ -0,0 +1,57 @@
package com.tiesheng.core.config.mybatis;
import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.autoconfigure.ConfigurationCustomizer;
import com.baomidou.mybatisplus.core.MybatisConfiguration;
import com.baomidou.mybatisplus.extension.MybatisMapWrapperFactory;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* @author hao
*/
@Configuration
public class MybatisPlusCustomizer {
/**
* 分页器配置
*
* @return
*/
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
PaginationInnerInterceptor paginationInnerInterceptor = new PaginationInnerInterceptor(DbType.MYSQL);
interceptor.addInnerInterceptor(paginationInnerInterceptor);
return interceptor;
}
/**
* map对象自动转驼峰
*
* @return
*/
@Bean
public ConfigurationCustomizer configurationCustomizer() {
return i -> {
i.setObjectWrapperFactory(new MybatisMapWrapperFactory());
};
}
/**
* map中保留null值
*
* @return
*/
@Bean
public MybatisConfiguration mybatisConfiguration() {
MybatisConfiguration configuration = new MybatisConfiguration();
configuration.setCallSettersOnNulls(true);
return configuration;
}
}

View File

@@ -0,0 +1,36 @@
package com.tiesheng.core.config.mybatis;
import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import org.apache.ibatis.reflection.MetaObject;
import org.springframework.stereotype.Component;
/**
* @author hao
*/
@Component
public class MybatisTimeMetaHandler implements MetaObjectHandler {
/**
* 在执行mybatisPlus的insert()时为我们自动给某些字段填充值这样的话我们就不需要手动给insert()里的实体类赋值了
*
* @param metaObject
*/
@Override
public void insertFill(MetaObject metaObject) {
// 其中方法参数中第一个是前面自动填充所对应的字段,第二个是要自动填充的值。第三个是指定实体类的对象
this.setFieldValByName("createTime", DateUtil.date(), metaObject);
this.setFieldValByName("updateTime", DateUtil.date(), metaObject);
}
/**
* 在执行mybatisPlus的update()时为我们自动给某些字段填充值这样的话我们就不需要手动给update()里的实体类赋值了
*
* @param metaObject
*/
@Override
public void updateFill(MetaObject metaObject) {
this.setFieldValByName("updateTime", DateUtil.date(), metaObject);
}
}

View File

@@ -0,0 +1,67 @@
package com.tiesheng.core.config.token;
import cn.hutool.extra.servlet.ServletUtil;
import cn.hutool.extra.spring.SpringUtil;
import cn.hutool.jwt.JWT;
import com.tiesheng.core.config.token.bean.TokenBean;
import com.tiesheng.core.util.servlet.ServletKit;
import com.tiesheng.util.exception.ApiException;
import com.tiesheng.util.pojos.ApiResp;
/**
* @author hao
*/
public class TokenParse {
/**
* 获取登陆信息
*
* @param token
* @return
*/
public static TokenBean get(String token) {
try {
TokenValidConfig tokenValidConfig = SpringUtil.getBean(TokenValidConfig.class);
TokenBean tokenBean = tokenValidConfig.getTokenBean(token);
if (tokenBean == null) {
JWT decode = JWT.of(token);
String id = decode.getPayload("id").toString();
String environmentType = decode.getPayload("environmentType").toString();
String service = decode.getPayload("service").toString();
String extra = decode.getPayload("extra").toString();
tokenBean = new TokenBean(id, environmentType, service);
tokenBean.setExtra(extra);
}
return tokenBean;
} catch (Exception e) {
throw new ApiException(ApiResp.respNeedLogin("请重新登录"));
}
}
/**
* 获取登录信息
*
* @return
*/
public static TokenBean get() {
String headerToken = ServletUtil.getHeader(ServletKit.getRequest(), "token", "utf-8");
return get(headerToken);
}
/**
* 获取用户id
*
* @return
*/
public static TokenBean getWithoutThr() {
TokenBean tokenBean = null;
try {
tokenBean = get();
} catch (Exception ignored) {
}
return tokenBean;
}
}

View File

@@ -0,0 +1,58 @@
package com.tiesheng.core.config.token;
import com.tiesheng.annotation.token.TokenIgnore;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import java.lang.reflect.Method;
/**
* @author hao
* @ProjectName CmccSpring
* @Copyright Hangzhou ShuoChuang Technology Co.,Ltd All Right Reserved
* @Description 这里是对文件的描述
* @data 2019-07-15
* @note 这里写文件的详细功能和改动
* @note
*/
@Aspect
@Component
public class TokenValidAspect {
/**
* 切入点
*/
@Pointcut("execution(* com..controller..*.*(..))")
public void methodArgs() {
}
/**
* 获取操作日志说明
*
* @param joinPoint
*/
@Before("methodArgs()")
public void before(JoinPoint joinPoint) {
// 过滤不要需要验证的接口
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
Method method = signature.getMethod();
TokenIgnore apiTokenIgnore = method.getAnnotation(TokenIgnore.class);
if (apiTokenIgnore != null) {
return;
}
// token验证
TokenParse.get();
}
}

View File

@@ -0,0 +1,46 @@
package com.tiesheng.core.config.token;
import cn.hutool.core.map.MapUtil;
import com.tiesheng.core.config.token.bean.TokenBean;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
import java.util.Map;
/**
* @author hao
*/
@Configuration
@ConfigurationProperties("tiesheng.token")
public class TokenValidConfig {
private Map<String, TokenBean> list = MapUtil.newHashMap();
/**
* 验证token
*
* @param token
* @return
*/
public TokenBean getTokenBean(String token) {
if (list == null) {
return null;
}
return list.get(token);
}
///////////////////////////////////////////////////////////////////////////
// setter\getter
///////////////////////////////////////////////////////////////////////////
public Map<String, TokenBean> getList() {
return list;
}
public void setList(Map<String, TokenBean> list) {
this.list = list;
}
}

View File

@@ -0,0 +1,72 @@
package com.tiesheng.core.config.token.bean;
import cn.hutool.jwt.JWT;
public class TokenBean {
private String id;
private String environmentType;
private String service;
private String extra;
public TokenBean() {
}
public TokenBean(String id, String environmentType, String service) {
this.id = id;
this.environmentType = environmentType;
this.service = service;
this.extra = "";
}
/**
* 设置token
*/
public String toToken() {
byte[] key = "%kIp9frQCu".getBytes();
return JWT.create()
.setPayload("id", id)
.setPayload("environmentType", environmentType)
.setPayload("service", service)
.setPayload("extra", extra)
.setPayload("time", System.currentTimeMillis())
.setKey(key)
.sign();
}
///////////////////////////////////////////////////////////////////////////
// setter\getter
///////////////////////////////////////////////////////////////////////////
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getEnvironmentType() {
return environmentType;
}
public void setEnvironmentType(String environmentType) {
this.environmentType = environmentType;
}
public String getService() {
return service;
}
public void setService(String service) {
this.service = service;
}
public String getExtra() {
return extra;
}
public void setExtra(String extra) {
this.extra = extra;
}
}

View File

@@ -0,0 +1,24 @@
package com.tiesheng.core.util.servlet;
import cn.hutool.extra.servlet.ServletUtil;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
public class ServletKit extends ServletUtil {
/**
* 获取当前线程的request
*
* @return
*/
public static HttpServletRequest getRequest() {
ServletRequestAttributes attributes = (ServletRequestAttributes)
RequestContextHolder.getRequestAttributes();
return attributes.getRequest();
}
}

View File

@@ -0,0 +1,21 @@
server:
compression:
enabled: true
## Spring配置
spring:
servlet:
multipart:
max-file-size: 20MB
web:
resources:
static-locations: classpath:/static/,file:static/
mvc:
pathmatch:
matching-strategy: ant_path_matcher
## 日志
logging:
file:
name: logs/tiesheng.log