Initial commit
This commit is contained in:
@@ -0,0 +1,13 @@
|
||||
package com.tiesheng.core;
|
||||
|
||||
import org.springframework.context.annotation.ComponentScan;
|
||||
|
||||
/**
|
||||
* @author hao
|
||||
*/
|
||||
|
||||
@ComponentScan({
|
||||
"com.tiesheng.core.**.*",
|
||||
})
|
||||
public class CoreAutoImportSelector {
|
||||
}
|
||||
@@ -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 {
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
21
tiesheng-web/src/main/resources/application.yml
Normal file
21
tiesheng-web/src/main/resources/application.yml
Normal 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
|
||||
Reference in New Issue
Block a user