perf(修改): 使用Redis验证登录
This commit is contained in:
parent
d0f34716a6
commit
1354d10622
|
@ -2,6 +2,7 @@
|
||||||
<project version="4">
|
<project version="4">
|
||||||
<component name="CompilerConfiguration">
|
<component name="CompilerConfiguration">
|
||||||
<annotationProcessing>
|
<annotationProcessing>
|
||||||
|
<profile default="true" name="Default" enabled="true" />
|
||||||
<profile name="Maven default annotation processors profile" enabled="true">
|
<profile name="Maven default annotation processors profile" enabled="true">
|
||||||
<sourceOutputDir name="target/generated-sources/annotations" />
|
<sourceOutputDir name="target/generated-sources/annotations" />
|
||||||
<sourceTestOutputDir name="target/generated-test-sources/test-annotations" />
|
<sourceTestOutputDir name="target/generated-test-sources/test-annotations" />
|
||||||
|
|
|
@ -0,0 +1,55 @@
|
||||||
|
package com.sky.common.config;
|
||||||
|
|
||||||
|
import com.github.xiaoymin.knife4j.spring.annotations.EnableKnife4j;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import springfox.documentation.builders.ApiInfoBuilder;
|
||||||
|
import springfox.documentation.builders.PathSelectors;
|
||||||
|
import springfox.documentation.builders.RequestHandlerSelectors;
|
||||||
|
import springfox.documentation.service.ApiInfo;
|
||||||
|
import springfox.documentation.service.Contact;
|
||||||
|
import springfox.documentation.spi.DocumentationType;
|
||||||
|
import springfox.documentation.spring.web.plugins.Docket;
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
@Slf4j
|
||||||
|
@EnableKnife4j
|
||||||
|
public class Knife4jConfiguration {
|
||||||
|
/**
|
||||||
|
* 通过knife4j生成接口文档
|
||||||
|
* 管理端接口
|
||||||
|
*
|
||||||
|
* @return Docket
|
||||||
|
*/
|
||||||
|
@Bean
|
||||||
|
public Docket docketAdmin() {
|
||||||
|
log.info("A管理端接口");
|
||||||
|
// 添加作者
|
||||||
|
springfox.documentation.service.Contact contact = new Contact("Bunny", "1319900154@qq.com", "1319900154@qq.com");
|
||||||
|
ApiInfo apiInfo = new ApiInfoBuilder().title("苍穹外卖项目接口文档").version("2.0").description("苍穹外卖项目接口文档").contact(contact).build();
|
||||||
|
return new Docket(DocumentationType.SWAGGER_2).groupName("A管理端接口")
|
||||||
|
.apiInfo(apiInfo).select().apis(RequestHandlerSelectors.basePackage("com.sky.controller.admin"))
|
||||||
|
.paths(PathSelectors.any()).build();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public Docket docketUser() {
|
||||||
|
log.info("B用户端接口");
|
||||||
|
|
||||||
|
ApiInfo apiInfo = new ApiInfoBuilder().title("苍穹外卖项目接口文档").version("2.0").description("苍穹外卖项目接口文档").build();
|
||||||
|
return new Docket(DocumentationType.SWAGGER_2).groupName("B用户端接口")
|
||||||
|
.apiInfo(apiInfo).select().apis(RequestHandlerSelectors.basePackage("com.sky.controller.user"))
|
||||||
|
.paths(PathSelectors.any()).build();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public Docket docketNotify() {
|
||||||
|
log.info("Pay支付接口");
|
||||||
|
|
||||||
|
ApiInfo apiInfo = new ApiInfoBuilder().title("苍穹外卖项目接口文档").version("2.0").description("苍穹外卖项目接口文档").build();
|
||||||
|
return new Docket(DocumentationType.SWAGGER_2).groupName("Pay支付接口")
|
||||||
|
.apiInfo(apiInfo).select().apis(RequestHandlerSelectors.basePackage("com.sky.controller.notify"))
|
||||||
|
.paths(PathSelectors.any()).build();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,95 @@
|
||||||
|
package com.sky.common.config;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonAutoDetect;
|
||||||
|
import com.fasterxml.jackson.annotation.PropertyAccessor;
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
import com.fasterxml.jackson.databind.SerializationFeature;
|
||||||
|
import com.fasterxml.jackson.databind.jsontype.impl.LaissezFaireSubTypeValidator;
|
||||||
|
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
|
||||||
|
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer;
|
||||||
|
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
|
||||||
|
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer;
|
||||||
|
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.cache.CacheManager;
|
||||||
|
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.connection.RedisConnectionFactory;
|
||||||
|
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
|
||||||
|
import org.springframework.data.redis.core.RedisTemplate;
|
||||||
|
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
|
||||||
|
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
|
||||||
|
import org.springframework.data.redis.serializer.RedisSerializationContext;
|
||||||
|
import org.springframework.data.redis.serializer.StringRedisSerializer;
|
||||||
|
|
||||||
|
import java.time.LocalDate;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.time.format.DateTimeFormatter;
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
@Slf4j
|
||||||
|
public class RedisConfiguration {
|
||||||
|
/**
|
||||||
|
* 使用StringRedisSerializer序列化为字符串
|
||||||
|
*/
|
||||||
|
@Bean
|
||||||
|
public RedisTemplate redisTemplate(LettuceConnectionFactory connectionFactory) {
|
||||||
|
RedisTemplate redisTemplate = new RedisTemplate();
|
||||||
|
redisTemplate.setConnectionFactory(connectionFactory);
|
||||||
|
// 设置key序列化为string
|
||||||
|
redisTemplate.setKeySerializer(new StringRedisSerializer());
|
||||||
|
// 设置value序列化为JSON,使用GenericJackson2JsonRedisSerializer替换默认序列化
|
||||||
|
redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer());
|
||||||
|
redisTemplate.setHashKeySerializer(new StringRedisSerializer());
|
||||||
|
redisTemplate.setHashValueSerializer(new GenericJackson2JsonRedisSerializer());
|
||||||
|
|
||||||
|
return redisTemplate;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 解决cache(@Cacheable)把数据缓存到redis中的value是乱码问题
|
||||||
|
*/
|
||||||
|
@Bean
|
||||||
|
@SuppressWarnings("all")
|
||||||
|
public CacheManager cacheManager(RedisConnectionFactory factory) {
|
||||||
|
StringRedisSerializer redisSerializer = new StringRedisSerializer();
|
||||||
|
// json序列化
|
||||||
|
Jackson2JsonRedisSerializer<Object> serializer = jsonRedisSerializer();
|
||||||
|
// 配置序列化
|
||||||
|
RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig();
|
||||||
|
RedisCacheConfiguration redisCacheConfiguration = config
|
||||||
|
.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(redisSerializer))
|
||||||
|
.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(serializer));
|
||||||
|
|
||||||
|
RedisCacheManager cacheManager = RedisCacheManager.builder(factory)
|
||||||
|
.cacheDefaults(redisCacheConfiguration).build();
|
||||||
|
return cacheManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 指定的日期模式
|
||||||
|
*/
|
||||||
|
public Jackson2JsonRedisSerializer<Object> jsonRedisSerializer() {
|
||||||
|
Jackson2JsonRedisSerializer<Object> serializer = new Jackson2JsonRedisSerializer<>(Object.class);
|
||||||
|
ObjectMapper mapper = new ObjectMapper();
|
||||||
|
// 设置ObjectMapper访问权限
|
||||||
|
mapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
|
||||||
|
// 记录序列化之后的数据类型,方便反序列化
|
||||||
|
mapper.activateDefaultTyping(LaissezFaireSubTypeValidator.instance, ObjectMapper.DefaultTyping.NON_FINAL);
|
||||||
|
// LocalDatetime序列化,默认不兼容jdk8日期序列化
|
||||||
|
JavaTimeModule timeModule = new JavaTimeModule();
|
||||||
|
timeModule.addDeserializer(LocalDate.class, new LocalDateDeserializer(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
|
||||||
|
timeModule.addSerializer(LocalDate.class, new LocalDateSerializer(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
|
||||||
|
|
||||||
|
timeModule.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
|
||||||
|
timeModule.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
|
||||||
|
// 关闭默认的日期格式化方式,默认UTC日期格式 yyyy-MM-dd’T’HH:mm:ss.SSS
|
||||||
|
mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
|
||||||
|
mapper.registerModule(timeModule);
|
||||||
|
|
||||||
|
serializer.setObjectMapper(mapper);
|
||||||
|
return serializer;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,16 @@
|
||||||
|
package com.sky.common.config;
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.web.client.RestTemplate;
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
@Slf4j
|
||||||
|
public class RestTemplateConfiguration {
|
||||||
|
@Bean
|
||||||
|
public RestTemplate restTemplate() {
|
||||||
|
log.info("注入restTemplate");
|
||||||
|
return new RestTemplate();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,59 @@
|
||||||
|
package com.sky.common.config;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
import com.sky.common.interceptor.JwtTokenUserInterceptor;
|
||||||
|
import com.sky.common.interceptor.RedisTokenAdminInterceptor;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.http.converter.HttpMessageConverter;
|
||||||
|
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
|
||||||
|
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
|
||||||
|
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
|
||||||
|
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
@Slf4j
|
||||||
|
public class WebMvcConfiguration extends WebMvcConfigurationSupport {
|
||||||
|
@Autowired
|
||||||
|
RedisTokenAdminInterceptor adminInterceptor;
|
||||||
|
@Autowired
|
||||||
|
JwtTokenUserInterceptor userInterceptor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 注册自定义拦截器
|
||||||
|
*
|
||||||
|
* @param registry InterceptorRegistry
|
||||||
|
*/
|
||||||
|
protected void addInterceptors(InterceptorRegistry registry) {
|
||||||
|
log.info("开始注册自定义拦截器...");
|
||||||
|
registry.addInterceptor(adminInterceptor).addPathPatterns("/admin/**")
|
||||||
|
.excludePathPatterns("/admin/employee/login");
|
||||||
|
registry.addInterceptor(userInterceptor).addPathPatterns("/user/**")
|
||||||
|
.excludePathPatterns("/user/user/login")
|
||||||
|
.excludePathPatterns("/user/shop/status");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 扩展Spring MVC框架的消息转化器
|
||||||
|
*
|
||||||
|
* @param converters 转换器
|
||||||
|
*/
|
||||||
|
protected void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
|
||||||
|
log.info("扩展消息转换器...");
|
||||||
|
// 创建一个消息转换器对象
|
||||||
|
MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
|
||||||
|
// 需要为消息转换器设置一个对象转换器,对象转换器可以将Java对象序列化为json数据
|
||||||
|
converter.setObjectMapper(new ObjectMapper());
|
||||||
|
// 将自己的消息转化器加入容器中
|
||||||
|
converters.add(0, converter);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void addResourceHandlers(ResourceHandlerRegistry registry) {
|
||||||
|
log.info("设置静态资源映射");
|
||||||
|
registry.addResourceHandler("/doc.html").addResourceLocations("classpath:/META-INF/resources/");
|
||||||
|
registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/");
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,19 @@
|
||||||
|
package com.sky.common.config;
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.web.socket.server.standard.ServerEndpointExporter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* WebSocket配置类,用于注册WebSocket的Bean
|
||||||
|
*/
|
||||||
|
@Configuration
|
||||||
|
@Slf4j
|
||||||
|
public class WebSocketConfiguration {
|
||||||
|
@Bean
|
||||||
|
public ServerEndpointExporter serverEndpointExporter() {
|
||||||
|
log.info("WebSocket配置类,用于注册WebSocket的Bean");
|
||||||
|
return new ServerEndpointExporter();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,30 @@
|
||||||
|
package com.sky.common.context;
|
||||||
|
|
||||||
|
public class BaseContext {
|
||||||
|
public static ThreadLocal<Long> threadLocal = new ThreadLocal<>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取当前用户id
|
||||||
|
*
|
||||||
|
* @return 用户id
|
||||||
|
*/
|
||||||
|
public static Long getUserId() {
|
||||||
|
return threadLocal.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置用户id
|
||||||
|
*
|
||||||
|
* @param userId 用户id
|
||||||
|
*/
|
||||||
|
public static void setUserId(Long userId) {
|
||||||
|
threadLocal.set(userId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 移出当前id
|
||||||
|
*/
|
||||||
|
public static void removeCurrentId() {
|
||||||
|
threadLocal.remove();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,36 @@
|
||||||
|
package com.sky.common.handler;
|
||||||
|
|
||||||
|
import com.sky.common.constant.MessageConstant;
|
||||||
|
import com.sky.common.exception.BaseException;
|
||||||
|
import com.sky.common.result.Result;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.web.bind.annotation.ExceptionHandler;
|
||||||
|
import org.springframework.web.bind.annotation.RestControllerAdvice;
|
||||||
|
|
||||||
|
import java.sql.SQLIntegrityConstraintViolationException;
|
||||||
|
|
||||||
|
@RestControllerAdvice
|
||||||
|
@Slf4j
|
||||||
|
public class GlobalExceptionHandler {
|
||||||
|
// 捕获业务异常
|
||||||
|
@ExceptionHandler
|
||||||
|
public Result<String> exceptionHandler(BaseException exception) {
|
||||||
|
log.error("异常信息:{}", exception.getMessage());
|
||||||
|
return Result.error(exception.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理SQL异常
|
||||||
|
public Result<String> exceptionHandler(SQLIntegrityConstraintViolationException exception) {
|
||||||
|
log.error("处理SQL异常:{}", exception.getMessage());
|
||||||
|
String message = exception.getMessage();
|
||||||
|
if (message.contains("Duplicate entry")) {
|
||||||
|
// 截取用户名
|
||||||
|
String username = message.split(" ")[2];
|
||||||
|
// 错误信息
|
||||||
|
String errorMessage = username + MessageConstant.ALREADY_EXISTS;
|
||||||
|
return Result.error(errorMessage);
|
||||||
|
} else {
|
||||||
|
return Result.error(MessageConstant.UNKNOWN_ERROR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,45 @@
|
||||||
|
package com.sky.common.interceptor;
|
||||||
|
|
||||||
|
import com.sky.common.constant.JwtClaimsConstant;
|
||||||
|
import com.sky.common.context.BaseContext;
|
||||||
|
import com.sky.common.properties.RedisTokenProperties;
|
||||||
|
import com.sky.common.utils.JwtUtil;
|
||||||
|
import io.jsonwebtoken.Claims;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.apache.http.HttpStatus;
|
||||||
|
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
import org.springframework.web.method.HandlerMethod;
|
||||||
|
import org.springframework.web.servlet.HandlerInterceptor;
|
||||||
|
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
@Slf4j
|
||||||
|
public class JwtTokenUserInterceptor implements HandlerInterceptor {
|
||||||
|
@Autowired
|
||||||
|
RedisTokenProperties redisTokenProperties;
|
||||||
|
|
||||||
|
public boolean preHandle(@NonNull HttpServletRequest request, @NonNull HttpServletResponse response, @NonNull Object handler) throws Exception {
|
||||||
|
// 判断当前拦截到的是Controller方法还是其它资源
|
||||||
|
if (!(handler instanceof HandlerMethod)) {
|
||||||
|
// 当前拦截到的不是动态方法,直接放行
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// 1. 从请求头中获取令牌
|
||||||
|
String token = request.getHeader(redisTokenProperties.getUserTokenName());
|
||||||
|
// 2. 校验令牌
|
||||||
|
log.info("jwt校验:{}", token);
|
||||||
|
try {
|
||||||
|
Claims claims = JwtUtil.parseJWT(redisTokenProperties.getUserSecretKey(), token);
|
||||||
|
Long userId = Long.valueOf(claims.get(JwtClaimsConstant.USER_ID).toString());
|
||||||
|
BaseContext.setUserId(userId);
|
||||||
|
return true;
|
||||||
|
} catch (Exception exception) {
|
||||||
|
response.setStatus(HttpStatus.SC_UNAUTHORIZED);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,49 @@
|
||||||
|
package com.sky.common.interceptor;
|
||||||
|
|
||||||
|
import com.sky.common.context.BaseContext;
|
||||||
|
import com.sky.common.properties.RedisTokenProperties;
|
||||||
|
import com.sky.common.utils.InterceptorUtil;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.data.redis.core.RedisTemplate;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
import org.springframework.web.method.HandlerMethod;
|
||||||
|
import org.springframework.web.servlet.HandlerInterceptor;
|
||||||
|
|
||||||
|
import javax.security.auth.login.LoginException;
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
@Slf4j
|
||||||
|
public class RedisTokenAdminInterceptor implements HandlerInterceptor {
|
||||||
|
@Autowired
|
||||||
|
private RedisTokenProperties redisTokenProperties;
|
||||||
|
@Autowired
|
||||||
|
private RedisTemplate<String, Object> redisTemplate;
|
||||||
|
|
||||||
|
public boolean preHandle(@NotNull HttpServletRequest request, @NotNull HttpServletResponse response, @NotNull Object handler) throws IOException, LoginException {
|
||||||
|
// 判断当前兰街道的是Controller的方法还是其它资源 拦截到的不是动态方法,直接放行
|
||||||
|
if (!(handler instanceof HandlerMethod)) return true;
|
||||||
|
|
||||||
|
// 1. 从请求头中获取令牌
|
||||||
|
String token = request.getHeader(redisTokenProperties.getAdminTokenName());
|
||||||
|
log.info("jwt校验:{}", token);
|
||||||
|
if (token == null) {
|
||||||
|
InterceptorUtil.unLoginInterceptor(response);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
Long empId = (Long) redisTemplate.opsForValue().get(token);
|
||||||
|
log.info("当前员工ID:{}", empId);
|
||||||
|
// 3. 通过放行
|
||||||
|
BaseContext.setUserId(empId);
|
||||||
|
return true;
|
||||||
|
} catch (Exception exception) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,47 @@
|
||||||
|
package com.sky.common.json;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
import com.fasterxml.jackson.databind.module.SimpleModule;
|
||||||
|
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer;
|
||||||
|
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
|
||||||
|
import com.fasterxml.jackson.datatype.jsr310.deser.LocalTimeDeserializer;
|
||||||
|
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer;
|
||||||
|
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
|
||||||
|
import com.fasterxml.jackson.datatype.jsr310.ser.LocalTimeSerializer;
|
||||||
|
|
||||||
|
import java.time.LocalDate;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.time.LocalTime;
|
||||||
|
import java.time.format.DateTimeFormatter;
|
||||||
|
|
||||||
|
import static com.fasterxml.jackson.databind.DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 对象映射器,基于Jackson将Java对象转为JSON,或者将JSON转为Java对象
|
||||||
|
* 将JSON转为Java对象过程--JSON反序列化Java对象
|
||||||
|
* 将Java对象转为JSON--序列化Java对象到JSON
|
||||||
|
*/
|
||||||
|
public class JacksonObjectMapper extends ObjectMapper {
|
||||||
|
public static final String DEFAULT_DATE_FORMAT = "yyyy-MM-dd";
|
||||||
|
// public static final String DEFAULT_DATE_TIME_FORMAT = "yyyy-MM-dd HH:mm:ss";
|
||||||
|
public static final String DEFAULT_DATE_TIME_FORMAT = "yyyy-MM-dd HH:mm";
|
||||||
|
public static final String DEFAULT_TIME_FORMAT = "HH:mm:ss";
|
||||||
|
|
||||||
|
public JacksonObjectMapper() {
|
||||||
|
super();
|
||||||
|
// 收到未知属性时不报异常
|
||||||
|
this.configure(FAIL_ON_UNKNOWN_PROPERTIES, false);
|
||||||
|
// 反序列化时,属性不存在的兼容处理
|
||||||
|
this.getDeserializationConfig().withoutFeatures(FAIL_ON_UNKNOWN_PROPERTIES);
|
||||||
|
|
||||||
|
SimpleModule simpleModule = new SimpleModule();
|
||||||
|
simpleModule.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_TIME_FORMAT)))
|
||||||
|
.addDeserializer(LocalDate.class, new LocalDateDeserializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_FORMAT)))
|
||||||
|
.addDeserializer(LocalTime.class, new LocalTimeDeserializer(DateTimeFormatter.ofPattern(DEFAULT_TIME_FORMAT)))
|
||||||
|
.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_TIME_FORMAT)))
|
||||||
|
.addSerializer(LocalDate.class, new LocalDateSerializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_FORMAT)))
|
||||||
|
.addSerializer(LocalTime.class, new LocalTimeSerializer(DateTimeFormatter.ofPattern(DEFAULT_TIME_FORMAT)));
|
||||||
|
// 注册功能模块 例如,可以添加自定义序列化器和反序列化器
|
||||||
|
this.registerModule(simpleModule);
|
||||||
|
}
|
||||||
|
}
|
|
@ -5,9 +5,9 @@ import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
@Component
|
@Component
|
||||||
@ConfigurationProperties(prefix = "sky.jwt")
|
@ConfigurationProperties(prefix = "sky.redis-token")
|
||||||
@Data
|
@Data
|
||||||
public class JwtProperties {
|
public class RedisTokenProperties {
|
||||||
/**
|
/**
|
||||||
* 管理端员工生成jwt令牌相关配置
|
* 管理端员工生成jwt令牌相关配置
|
||||||
*/
|
*/
|
|
@ -0,0 +1,19 @@
|
||||||
|
package com.sky.common.result;
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 封装分页查询结果
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@AllArgsConstructor
|
||||||
|
@NoArgsConstructor
|
||||||
|
public class PageResult<T> implements Serializable {
|
||||||
|
private long total; // 总记录数
|
||||||
|
private List<T> records; // 当前页数据集合
|
||||||
|
}
|
|
@ -0,0 +1,40 @@
|
||||||
|
package com.sky.common.result;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 后端统一返回结果
|
||||||
|
*
|
||||||
|
* @param <T>
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class Result<T> implements Serializable {
|
||||||
|
private Integer code; // 编码:1成功,0和其它数字为失败
|
||||||
|
private String message; // 错误信息
|
||||||
|
private T data; // 数据
|
||||||
|
|
||||||
|
// 成功
|
||||||
|
public static <T> Result<T> success() {
|
||||||
|
Result<T> result = new Result<>();
|
||||||
|
result.code = 1;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 有数据返回
|
||||||
|
public static <T> Result<T> success(T object) {
|
||||||
|
Result<T> result = new Result<>();
|
||||||
|
result.code = 1;
|
||||||
|
result.data = object;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 错误返回
|
||||||
|
public static <T> Result<T> error(String message) {
|
||||||
|
Result<T> result = new Result<>();
|
||||||
|
result.code = 0;
|
||||||
|
result.message = message;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,168 @@
|
||||||
|
package com.sky.common.utils;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson.JSONObject;
|
||||||
|
import org.apache.http.NameValuePair;
|
||||||
|
import org.apache.http.client.config.RequestConfig;
|
||||||
|
import org.apache.http.client.entity.UrlEncodedFormEntity;
|
||||||
|
import org.apache.http.client.methods.CloseableHttpResponse;
|
||||||
|
import org.apache.http.client.methods.HttpGet;
|
||||||
|
import org.apache.http.client.methods.HttpPost;
|
||||||
|
import org.apache.http.client.utils.URIBuilder;
|
||||||
|
import org.apache.http.entity.StringEntity;
|
||||||
|
import org.apache.http.impl.client.CloseableHttpClient;
|
||||||
|
import org.apache.http.impl.client.HttpClients;
|
||||||
|
import org.apache.http.message.BasicNameValuePair;
|
||||||
|
import org.apache.http.util.EntityUtils;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.URI;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Http工具类
|
||||||
|
*/
|
||||||
|
public class HttpClientUtil {
|
||||||
|
|
||||||
|
static final int TIMEOUT_MSEC = 5 * 1000;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 发送GET方式请求
|
||||||
|
*/
|
||||||
|
public static String doGet(String url, Map<String, String> paramMap) {
|
||||||
|
// 创建Httpclient对象
|
||||||
|
CloseableHttpClient httpClient = HttpClients.createDefault();
|
||||||
|
|
||||||
|
String result = "";
|
||||||
|
CloseableHttpResponse response = null;
|
||||||
|
|
||||||
|
try {
|
||||||
|
URIBuilder builder = new URIBuilder(url);
|
||||||
|
if (paramMap != null) {
|
||||||
|
for (String key : paramMap.keySet()) {
|
||||||
|
builder.addParameter(key, paramMap.get(key));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
URI uri = builder.build();
|
||||||
|
|
||||||
|
// 创建GET请求
|
||||||
|
HttpGet httpGet = new HttpGet(uri);
|
||||||
|
|
||||||
|
// 发送请求
|
||||||
|
response = httpClient.execute(httpGet);
|
||||||
|
|
||||||
|
// 判断响应状态
|
||||||
|
if (response.getStatusLine().getStatusCode() == 200) {
|
||||||
|
result = EntityUtils.toString(response.getEntity(), "UTF-8");
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} finally {
|
||||||
|
try {
|
||||||
|
response.close();
|
||||||
|
httpClient.close();
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 发送POST方式请求
|
||||||
|
*/
|
||||||
|
public static String doPost(String url, Map<String, String> paramMap) throws IOException {
|
||||||
|
// 创建Httpclient对象
|
||||||
|
CloseableHttpClient httpClient = HttpClients.createDefault();
|
||||||
|
CloseableHttpResponse response = null;
|
||||||
|
String resultString = "";
|
||||||
|
|
||||||
|
try {
|
||||||
|
// 创建Http Post请求
|
||||||
|
HttpPost httpPost = new HttpPost(url);
|
||||||
|
|
||||||
|
// 创建参数列表
|
||||||
|
if (paramMap != null) {
|
||||||
|
List<NameValuePair> paramList = new ArrayList();
|
||||||
|
for (Map.Entry<String, String> param : paramMap.entrySet()) {
|
||||||
|
paramList.add(new BasicNameValuePair(param.getKey(), param.getValue()));
|
||||||
|
}
|
||||||
|
// 模拟表单
|
||||||
|
UrlEncodedFormEntity entity = new UrlEncodedFormEntity(paramList);
|
||||||
|
httpPost.setEntity(entity);
|
||||||
|
}
|
||||||
|
|
||||||
|
httpPost.setConfig(builderRequestConfig());
|
||||||
|
|
||||||
|
// 执行http请求
|
||||||
|
response = httpClient.execute(httpPost);
|
||||||
|
|
||||||
|
resultString = EntityUtils.toString(response.getEntity(), "UTF-8");
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw e;
|
||||||
|
} finally {
|
||||||
|
try {
|
||||||
|
response.close();
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return resultString;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 发送POST方式请求
|
||||||
|
*/
|
||||||
|
public static String doPost4Json(String url, Map<String, String> paramMap) throws IOException {
|
||||||
|
// 创建Httpclient对象
|
||||||
|
CloseableHttpClient httpClient = HttpClients.createDefault();
|
||||||
|
CloseableHttpResponse response = null;
|
||||||
|
String resultString = "";
|
||||||
|
|
||||||
|
try {
|
||||||
|
// 创建Http Post请求
|
||||||
|
HttpPost httpPost = new HttpPost(url);
|
||||||
|
|
||||||
|
if (paramMap != null) {
|
||||||
|
// 构造json格式数据
|
||||||
|
JSONObject jsonObject = new JSONObject();
|
||||||
|
for (Map.Entry<String, String> param : paramMap.entrySet()) {
|
||||||
|
jsonObject.put(param.getKey(), param.getValue());
|
||||||
|
}
|
||||||
|
StringEntity entity = new StringEntity(jsonObject.toString(), "utf-8");
|
||||||
|
// 设置请求编码
|
||||||
|
entity.setContentEncoding("utf-8");
|
||||||
|
// 设置数据类型
|
||||||
|
entity.setContentType("application/json");
|
||||||
|
httpPost.setEntity(entity);
|
||||||
|
}
|
||||||
|
|
||||||
|
httpPost.setConfig(builderRequestConfig());
|
||||||
|
|
||||||
|
// 执行http请求
|
||||||
|
response = httpClient.execute(httpPost);
|
||||||
|
|
||||||
|
resultString = EntityUtils.toString(response.getEntity(), "UTF-8");
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw e;
|
||||||
|
} finally {
|
||||||
|
try {
|
||||||
|
response.close();
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return resultString;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static RequestConfig builderRequestConfig() {
|
||||||
|
return RequestConfig.custom()
|
||||||
|
.setConnectTimeout(TIMEOUT_MSEC)
|
||||||
|
.setConnectionRequestTimeout(TIMEOUT_MSEC)
|
||||||
|
.setSocketTimeout(TIMEOUT_MSEC).build();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,42 @@
|
||||||
|
package com.sky.common.utils;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson.JSON;
|
||||||
|
import com.sky.common.result.Result;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
|
public class InterceptorUtil {
|
||||||
|
/**
|
||||||
|
* 用户未登录返回响应
|
||||||
|
*
|
||||||
|
* @param response 返回体
|
||||||
|
*/
|
||||||
|
public static void unLoginInterceptor(HttpServletResponse response) throws IOException {
|
||||||
|
log.info("用户未登录");
|
||||||
|
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
|
||||||
|
response.setContentType("application/json");
|
||||||
|
response.setCharacterEncoding("UTF-8");
|
||||||
|
Result<String> result = new Result<>();
|
||||||
|
result.setCode(HttpServletResponse.SC_UNAUTHORIZED);
|
||||||
|
result.setData("未登录");
|
||||||
|
result.setMessage("请先登录");
|
||||||
|
// 将消息写入响应体
|
||||||
|
response.getWriter().write(JSON.toJSONString(result));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void otherLoginInterceptor(HttpServletResponse response) throws IOException {
|
||||||
|
log.info("其它异常");
|
||||||
|
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
|
||||||
|
response.setContentType("application/json");
|
||||||
|
response.setCharacterEncoding("UTF-8");
|
||||||
|
Result<String> result = new Result<>();
|
||||||
|
result.setCode(HttpServletResponse.SC_UNAUTHORIZED);
|
||||||
|
result.setData("未登录");
|
||||||
|
result.setMessage("请先登录");
|
||||||
|
// 将消息写入响应体
|
||||||
|
response.getWriter().write(JSON.toJSONString(result));
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,53 @@
|
||||||
|
package com.sky.common.utils;
|
||||||
|
|
||||||
|
import io.jsonwebtoken.Claims;
|
||||||
|
import io.jsonwebtoken.JwtBuilder;
|
||||||
|
import io.jsonwebtoken.Jwts;
|
||||||
|
import io.jsonwebtoken.SignatureAlgorithm;
|
||||||
|
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public class JwtUtil {
|
||||||
|
/**
|
||||||
|
* 生成JWT
|
||||||
|
* 使用Hs256算法, 私匙使用固定秘钥
|
||||||
|
*
|
||||||
|
* @param secretKey jwt秘钥
|
||||||
|
* @param ttlMillis jwt过期时间(毫秒)
|
||||||
|
* @param claims 设置的信息
|
||||||
|
* @return 加密后JWT
|
||||||
|
*/
|
||||||
|
public static String createJWT(String secretKey, long ttlMillis, Map<String, Object> claims) {
|
||||||
|
// 指定签名的时候使用的签名算法,也就是header那部分
|
||||||
|
SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;
|
||||||
|
// 生成JWT的时间
|
||||||
|
long expMillis = System.currentTimeMillis() + ttlMillis;
|
||||||
|
Date date = new Date(expMillis);
|
||||||
|
JwtBuilder builder = Jwts.builder()
|
||||||
|
// 如果有私有声明,一定要先设置这个自己创建的私有的声明,这个是给builder的claim赋值,一旦写在标准的声明赋值之后,就是覆盖了那些标准的声明的
|
||||||
|
.setClaims(claims)
|
||||||
|
// 设置签名使用的签名算法和签名使用的秘钥
|
||||||
|
.signWith(signatureAlgorithm, secretKey.getBytes(StandardCharsets.UTF_8))
|
||||||
|
// 设置过期时间
|
||||||
|
.setExpiration(date);
|
||||||
|
return builder.compact();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Token解密
|
||||||
|
*
|
||||||
|
* @param secretKey jwt秘钥
|
||||||
|
* @param token token
|
||||||
|
* @return 解密后数据
|
||||||
|
*/
|
||||||
|
public static Claims parseJWT(String secretKey, String token) {
|
||||||
|
// 得到DefaultJwtParser
|
||||||
|
return Jwts.parser()
|
||||||
|
// 设置签名的秘钥
|
||||||
|
.setSigningKey(secretKey.getBytes(StandardCharsets.UTF_8))
|
||||||
|
// 设置需要解析的jwt
|
||||||
|
.parseClaimsJwt(token).getBody();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,34 @@
|
||||||
|
package com.sky.common.utils;
|
||||||
|
|
||||||
|
import java.security.MessageDigest;
|
||||||
|
import java.security.NoSuchAlgorithmException;
|
||||||
|
|
||||||
|
|
||||||
|
public final class MD5 {
|
||||||
|
|
||||||
|
public static String encrypt(String strSrc) {
|
||||||
|
try {
|
||||||
|
char[] hexChars = {'0', '1', '2', '3', '4', '5', '6', '7', '8',
|
||||||
|
'9', 'a', 'b', 'c', 'd', 'e', 'f'};
|
||||||
|
byte[] bytes = strSrc.getBytes();
|
||||||
|
MessageDigest md = MessageDigest.getInstance("MD5");
|
||||||
|
md.update(bytes);
|
||||||
|
bytes = md.digest();
|
||||||
|
int j = bytes.length;
|
||||||
|
char[] chars = new char[j * 2];
|
||||||
|
int k = 0;
|
||||||
|
for (byte b : bytes) {
|
||||||
|
chars[k++] = hexChars[b >>> 4 & 0xf];
|
||||||
|
chars[k++] = hexChars[b & 0xf];
|
||||||
|
}
|
||||||
|
return new String(chars);
|
||||||
|
} catch (NoSuchAlgorithmException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
throw new RuntimeException("MD5加密出错!!+" + e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
System.out.println(MD5.encrypt("111111"));
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,112 @@
|
||||||
|
package com.sky.common.utils;
|
||||||
|
|
||||||
|
|
||||||
|
import com.sky.common.properties.MinioProperties;
|
||||||
|
import io.minio.*;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import java.io.InputStream;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
@Slf4j
|
||||||
|
public class MinioUtils {
|
||||||
|
private final MinioClient minioClient;
|
||||||
|
private final MinioProperties minioProperties;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 判断桶是否存在
|
||||||
|
*
|
||||||
|
* @param bucketName String
|
||||||
|
* @return found
|
||||||
|
*/
|
||||||
|
public boolean bucketExists(String bucketName) {
|
||||||
|
boolean found = false;
|
||||||
|
try {
|
||||||
|
found = minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build());
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return found;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 如果桶不存在就新建
|
||||||
|
*
|
||||||
|
* @param bucketName String
|
||||||
|
*/
|
||||||
|
public void bucketCreate(String bucketName) {
|
||||||
|
boolean exists = bucketExists(bucketName);
|
||||||
|
if (!exists) {
|
||||||
|
try {
|
||||||
|
minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucketName).build());
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 上传文件
|
||||||
|
*
|
||||||
|
* @param fileName 文件名
|
||||||
|
* @param inputStream 输入流
|
||||||
|
* @param size 文件大小
|
||||||
|
*/
|
||||||
|
public String uploadFile(String bucketName, String fileName, InputStream inputStream, Long size) {
|
||||||
|
try {
|
||||||
|
minioClient.putObject(PutObjectArgs.builder()
|
||||||
|
.bucket(bucketName)
|
||||||
|
.object(fileName)
|
||||||
|
.stream(inputStream, size, -1)
|
||||||
|
.build());
|
||||||
|
return minioProperties.getEndpointUrl() + "/" + bucketName + "/" + fileName;
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 上传文件
|
||||||
|
*
|
||||||
|
* @param fileName 文件名
|
||||||
|
* @param inputStream 输入流
|
||||||
|
* @param size 文件大小
|
||||||
|
* @param contentType 文件类型
|
||||||
|
*/
|
||||||
|
public String uploadFile(String bucketName, String fileName, InputStream inputStream, Long size, String contentType) {
|
||||||
|
try {
|
||||||
|
minioClient.putObject(PutObjectArgs.builder()
|
||||||
|
.bucket(bucketName)
|
||||||
|
.object(fileName)
|
||||||
|
.stream(inputStream, size, -1)
|
||||||
|
.contentType(contentType)
|
||||||
|
.build());
|
||||||
|
return minioProperties.getEndpointUrl() + "/" + bucketName + "/" + fileName;
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取文件
|
||||||
|
*
|
||||||
|
* @param bucketName 桶名称
|
||||||
|
* @param fileName 对象名称
|
||||||
|
*/
|
||||||
|
public InputStream getFile(String bucketName, String fileName) {
|
||||||
|
try {
|
||||||
|
return minioClient.getObject(GetObjectArgs.builder()
|
||||||
|
.bucket(bucketName)
|
||||||
|
.object(fileName)
|
||||||
|
.build());
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,20 @@
|
||||||
|
package com.sky.common.utils;
|
||||||
|
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.springframework.data.redis.core.RedisTemplate;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class RedisUtil {
|
||||||
|
private static final RedisTemplate<Object, Object> redisTemplate = new RedisTemplate<>();
|
||||||
|
|
||||||
|
public static void cleanCache(String key) {
|
||||||
|
Set<Object> keys = redisTemplate.keys(key);
|
||||||
|
if (keys != null) {
|
||||||
|
redisTemplate.delete(keys);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,27 @@
|
||||||
|
package com.sky.common.utils;
|
||||||
|
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.springframework.core.ParameterizedTypeReference;
|
||||||
|
import org.springframework.http.*;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
import org.springframework.web.client.RestTemplate;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class RestTemplateUtil<T> implements Serializable {
|
||||||
|
private final RestTemplate restTemplate;
|
||||||
|
|
||||||
|
public ResponseEntity<?> requestGet(String url, T t) {
|
||||||
|
HttpHeaders headers = new HttpHeaders();
|
||||||
|
headers.setContentType(MediaType.APPLICATION_JSON);
|
||||||
|
|
||||||
|
HttpEntity<T> entity = new HttpEntity<T>(t, headers);
|
||||||
|
|
||||||
|
ResponseEntity<?> response = restTemplate.exchange(url, HttpMethod.GET, entity, new ParameterizedTypeReference<T>() {
|
||||||
|
});
|
||||||
|
|
||||||
|
return response.getStatusCode().is2xxSuccessful() ? response : null;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,225 @@
|
||||||
|
package com.sky.common.utils;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson.JSONObject;
|
||||||
|
import com.sky.common.context.BaseContext;
|
||||||
|
import com.sky.common.properties.WeChatProperties;
|
||||||
|
import com.wechat.pay.contrib.apache.httpclient.WechatPayHttpClientBuilder;
|
||||||
|
import com.wechat.pay.contrib.apache.httpclient.util.PemUtil;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.apache.commons.lang.RandomStringUtils;
|
||||||
|
import org.apache.http.HttpHeaders;
|
||||||
|
import org.apache.http.client.methods.CloseableHttpResponse;
|
||||||
|
import org.apache.http.client.methods.HttpGet;
|
||||||
|
import org.apache.http.client.methods.HttpPost;
|
||||||
|
import org.apache.http.entity.ContentType;
|
||||||
|
import org.apache.http.entity.StringEntity;
|
||||||
|
import org.apache.http.impl.client.CloseableHttpClient;
|
||||||
|
import org.apache.http.util.EntityUtils;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileInputStream;
|
||||||
|
import java.io.FileNotFoundException;
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.math.RoundingMode;
|
||||||
|
import java.security.PrivateKey;
|
||||||
|
import java.security.cert.X509Certificate;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 微信支付工具类
|
||||||
|
*/
|
||||||
|
@Component
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class WeChatPayUtil {
|
||||||
|
// 微信支付下单接口地址
|
||||||
|
public static final String JSAPI = "https://api.mch.weixin.qq.com/v3/pay/transactions/jsapi";
|
||||||
|
// 申请退款接口地址
|
||||||
|
public static final String REFUNDS = "https://api.mch.weixin.qq.com/v3/refund/domestic/refunds";
|
||||||
|
private final WeChatProperties weChatProperties;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取调用微信接口的客户端工具对象
|
||||||
|
*/
|
||||||
|
private CloseableHttpClient getClient() {
|
||||||
|
PrivateKey merchantPrivateKey = null;
|
||||||
|
try {
|
||||||
|
// merchantPrivateKey商户API私钥,如何加载商户API私钥请看常见问题
|
||||||
|
merchantPrivateKey = PemUtil.loadPrivateKey(new FileInputStream(new File(weChatProperties.getPrivateKeyFilePath())));
|
||||||
|
// 加载平台证书文件
|
||||||
|
X509Certificate x509Certificate = PemUtil.loadCertificate(new FileInputStream(new File(weChatProperties.getWeChatPayCertFilePath())));
|
||||||
|
// wechatPayCertificates微信支付平台证书列表。你也可以使用后面章节提到的“定时更新平台证书功能”,而不需要关心平台证书的来龙去脉
|
||||||
|
List<X509Certificate> wechatPayCertificates = Collections.singletonList(x509Certificate);
|
||||||
|
|
||||||
|
WechatPayHttpClientBuilder builder = WechatPayHttpClientBuilder.create()
|
||||||
|
.withMerchant(weChatProperties.getMchid(), weChatProperties.getMchSerialNo(), merchantPrivateKey)
|
||||||
|
.withWechatPay(wechatPayCertificates);
|
||||||
|
|
||||||
|
// 通过WechatPayHttpClientBuilder构造的HttpClient,会自动的处理签名和验签
|
||||||
|
CloseableHttpClient httpClient = builder.build();
|
||||||
|
return httpClient;
|
||||||
|
} catch (FileNotFoundException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 发送post方式请求
|
||||||
|
*
|
||||||
|
* @param url
|
||||||
|
* @param body
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private String post(String url, String body) throws Exception {
|
||||||
|
CloseableHttpClient httpClient = getClient();
|
||||||
|
|
||||||
|
HttpPost httpPost = new HttpPost(url);
|
||||||
|
httpPost.addHeader(HttpHeaders.ACCEPT, ContentType.APPLICATION_JSON.toString());
|
||||||
|
httpPost.addHeader(HttpHeaders.CONTENT_TYPE, ContentType.APPLICATION_JSON.toString());
|
||||||
|
httpPost.addHeader("Wechatpay-Serial", weChatProperties.getMchSerialNo());
|
||||||
|
httpPost.setEntity(new StringEntity(body, "UTF-8"));
|
||||||
|
|
||||||
|
CloseableHttpResponse response = httpClient.execute(httpPost);
|
||||||
|
try {
|
||||||
|
return EntityUtils.toString(response.getEntity());
|
||||||
|
} finally {
|
||||||
|
httpClient.close();
|
||||||
|
response.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 发送get方式请求
|
||||||
|
*
|
||||||
|
* @param url
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private String get(String url) throws Exception {
|
||||||
|
CloseableHttpClient httpClient = getClient();
|
||||||
|
|
||||||
|
HttpGet httpGet = new HttpGet(url);
|
||||||
|
httpGet.addHeader(HttpHeaders.ACCEPT, ContentType.APPLICATION_JSON.toString());
|
||||||
|
httpGet.addHeader(HttpHeaders.CONTENT_TYPE, ContentType.APPLICATION_JSON.toString());
|
||||||
|
httpGet.addHeader("Wechatpay-Serial", weChatProperties.getMchSerialNo());
|
||||||
|
|
||||||
|
CloseableHttpResponse response = httpClient.execute(httpGet);
|
||||||
|
try {
|
||||||
|
return EntityUtils.toString(response.getEntity());
|
||||||
|
} finally {
|
||||||
|
httpClient.close();
|
||||||
|
response.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* jsapi下单
|
||||||
|
*
|
||||||
|
* @param orderNum 商户订单号
|
||||||
|
* @param total 总金额
|
||||||
|
* @param description 商品描述
|
||||||
|
* @param openid 微信用户的openid
|
||||||
|
*/
|
||||||
|
private String jsapi(String orderNum, BigDecimal total, String description, String openid) throws Exception {
|
||||||
|
JSONObject jsonObject = new JSONObject();
|
||||||
|
jsonObject.put("appid", weChatProperties.getAppid());
|
||||||
|
jsonObject.put("mchid", weChatProperties.getMchid());
|
||||||
|
jsonObject.put("description", description);
|
||||||
|
jsonObject.put("out_trade_no", orderNum);
|
||||||
|
jsonObject.put("notify_url", weChatProperties.getNotifyUrl());
|
||||||
|
|
||||||
|
JSONObject amount = new JSONObject();
|
||||||
|
amount.put("total", total.multiply(new BigDecimal(100)).setScale(2, RoundingMode.HALF_UP).intValue());
|
||||||
|
amount.put("currency", "CNY");
|
||||||
|
|
||||||
|
jsonObject.put("amount", amount);
|
||||||
|
|
||||||
|
JSONObject payer = new JSONObject();
|
||||||
|
payer.put("openid", openid);
|
||||||
|
|
||||||
|
jsonObject.put("payer", payer);
|
||||||
|
|
||||||
|
String body = jsonObject.toJSONString();
|
||||||
|
return post(JSAPI, body);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 小程序支付
|
||||||
|
*
|
||||||
|
* @param orderNum 商户订单号
|
||||||
|
* @param total 金额,单位 元
|
||||||
|
* @param description 商品描述
|
||||||
|
* @param openid 微信用户的openid
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public JSONObject pay(String orderNum, BigDecimal total, String description, String openid) throws Exception {
|
||||||
|
// 统一下单,生成预支付交易单
|
||||||
|
// String bodyAsString = jsapi(orderNum, total, description, openid);
|
||||||
|
// 解析返回结果
|
||||||
|
// JSONObject jsonObject = JSON.parseObject(bodyAsString);
|
||||||
|
|
||||||
|
// String prepayId = jsonObject.getString("prepay_id");
|
||||||
|
String prepayId = "bunny-" + UUID.randomUUID();
|
||||||
|
String timeStamp = String.valueOf(System.currentTimeMillis() / 1000);
|
||||||
|
String nonceStr = RandomStringUtils.randomNumeric(32);
|
||||||
|
ArrayList<Object> list = new ArrayList<>();
|
||||||
|
list.add(weChatProperties.getAppid());
|
||||||
|
list.add(timeStamp);
|
||||||
|
list.add(nonceStr);
|
||||||
|
list.add("prepay_id=" + prepayId);
|
||||||
|
// 二次签名,调起支付需要重新签名
|
||||||
|
// StringBuilder stringBuilder = new StringBuilder();
|
||||||
|
// for (Object o : list) {
|
||||||
|
// stringBuilder.append(o).append("\n");
|
||||||
|
// }
|
||||||
|
// String signMessage = stringBuilder.toString();
|
||||||
|
// byte[] message = signMessage.getBytes();
|
||||||
|
|
||||||
|
// Signature signature = Signature.getInstance("SHA256withRSA");
|
||||||
|
// signature.initSign(PemUtil.loadPrivateKey(Files.newInputStream(new File(weChatProperties.getPrivateKeyFilePath()).toPath())));
|
||||||
|
// signature.update(message);
|
||||||
|
// String packageSign = Base64.getEncoder().encodeToString(signature.sign());
|
||||||
|
|
||||||
|
// 构造数据给微信小程序,用于调起微信支付
|
||||||
|
JSONObject jo = new JSONObject();
|
||||||
|
jo.put("timeStamp", timeStamp);
|
||||||
|
jo.put("nonceStr", nonceStr);
|
||||||
|
jo.put("package", "prepay_id=" + prepayId);
|
||||||
|
jo.put("signType", "RSA");
|
||||||
|
jo.put("paySign", BaseContext.getUserId() + "-" + prepayId);
|
||||||
|
|
||||||
|
return jo;
|
||||||
|
// return jsonObject;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 申请退款
|
||||||
|
*
|
||||||
|
* @param outTradeNo 商户订单号
|
||||||
|
* @param outRefundNo 商户退款单号
|
||||||
|
* @param refund 退款金额
|
||||||
|
* @param total 原订单金额
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public String refund(String outTradeNo, String outRefundNo, BigDecimal refund, BigDecimal total) throws Exception {
|
||||||
|
JSONObject jsonObject = new JSONObject();
|
||||||
|
jsonObject.put("out_trade_no", outTradeNo);
|
||||||
|
jsonObject.put("out_refund_no", outRefundNo);
|
||||||
|
|
||||||
|
JSONObject amount = new JSONObject();
|
||||||
|
amount.put("refund", refund.multiply(new BigDecimal(100)).setScale(2, RoundingMode.HALF_UP).intValue());
|
||||||
|
amount.put("total", total.multiply(new BigDecimal(100)).setScale(2, RoundingMode.HALF_UP).intValue());
|
||||||
|
amount.put("currency", "CNY");
|
||||||
|
|
||||||
|
jsonObject.put("amount", amount);
|
||||||
|
jsonObject.put("notify_url", weChatProperties.getRefundNotifyUrl());
|
||||||
|
|
||||||
|
String body = jsonObject.toJSONString();
|
||||||
|
|
||||||
|
// 调用申请退款接口
|
||||||
|
return post(REFUNDS, body);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
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>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<parent>
|
<parent>
|
||||||
|
@ -22,5 +22,9 @@
|
||||||
<groupId>org.projectlombok</groupId>
|
<groupId>org.projectlombok</groupId>
|
||||||
<artifactId>lombok</artifactId>
|
<artifactId>lombok</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.github.xiaoymin</groupId>
|
||||||
|
<artifactId>knife4j-spring-boot-starter</artifactId>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
</project>
|
</project>
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
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>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>com.sky</groupId>
|
<groupId>com.sky</groupId>
|
||||||
<artifactId>dev-sky-serve-v1</artifactId>
|
<artifactId>dev-sky-serve-v1</artifactId>
|
||||||
|
@ -9,26 +12,12 @@
|
||||||
|
|
||||||
<artifactId>sky-server</artifactId>
|
<artifactId>sky-server</artifactId>
|
||||||
<packaging>jar</packaging>
|
<packaging>jar</packaging>
|
||||||
|
|
||||||
<name>sky-server</name>
|
|
||||||
<url>http://maven.apache.org</url>
|
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
|
<maven.compiler.source>8</maven.compiler.source>
|
||||||
|
<maven.compiler.target>8</maven.compiler.target>
|
||||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<dependency>
|
|
||||||
<groupId>com.sky</groupId>
|
|
||||||
<artifactId>sky-common</artifactId>
|
|
||||||
<version>1.0-SNAPSHOT</version>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>com.sky</groupId>
|
|
||||||
<artifactId>sky-pojo</artifactId>
|
|
||||||
<version>1.0-SNAPSHOT</version>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework.boot</groupId>
|
<groupId>org.springframework.boot</groupId>
|
||||||
<artifactId>spring-boot-starter</artifactId>
|
<artifactId>spring-boot-starter</artifactId>
|
||||||
|
@ -131,6 +120,17 @@
|
||||||
<artifactId>junit</artifactId>
|
<artifactId>junit</artifactId>
|
||||||
<version>4.13.1</version>
|
<version>4.13.1</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.sky</groupId>
|
||||||
|
<artifactId>sky-common</artifactId>
|
||||||
|
<version>1.0-SNAPSHOT</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.sky</groupId>
|
||||||
|
<artifactId>sky-pojo</artifactId>
|
||||||
|
<version>1.0-SNAPSHOT</version>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
|
|
|
@ -14,6 +14,6 @@ import org.springframework.transaction.annotation.EnableTransactionManagement;
|
||||||
@Slf4j
|
@Slf4j
|
||||||
public class SkyApplication {
|
public class SkyApplication {
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
SpringApplication.run(SkyApplication.class);
|
SpringApplication.run(SkyApplication.class, args);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,14 @@
|
||||||
|
package com.sky.annotation;
|
||||||
|
|
||||||
|
import com.sky.common.enumeration.OperationType;
|
||||||
|
|
||||||
|
import java.lang.annotation.ElementType;
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
|
@Target(ElementType.METHOD)
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
public @interface AutoFill {
|
||||||
|
OperationType value();
|
||||||
|
}
|
|
@ -0,0 +1,13 @@
|
||||||
|
package com.sky.aspect;
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.aspectj.lang.annotation.Aspect;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
/**
|
||||||
|
* 自定义切面,实现公共字段自动填充处理逻辑
|
||||||
|
*/
|
||||||
|
@Aspect
|
||||||
|
@Component
|
||||||
|
@Slf4j
|
||||||
|
public class AutoFillAspect {
|
||||||
|
}
|
|
@ -1,10 +1,7 @@
|
||||||
package com.sky.controller.admin;
|
package com.sky.controller.admin;
|
||||||
|
|
||||||
import com.sky.common.constant.JwtClaimsConstant;
|
|
||||||
import com.sky.common.properties.JwtProperties;
|
|
||||||
import com.sky.common.result.PageResult;
|
import com.sky.common.result.PageResult;
|
||||||
import com.sky.common.result.Result;
|
import com.sky.common.result.Result;
|
||||||
import com.sky.common.utils.JwtUtil;
|
|
||||||
import com.sky.pojo.dto.EmployeeDTO;
|
import com.sky.pojo.dto.EmployeeDTO;
|
||||||
import com.sky.pojo.dto.EmployeeLoginDTO;
|
import com.sky.pojo.dto.EmployeeLoginDTO;
|
||||||
import com.sky.pojo.dto.EmployeePageQueryDTO;
|
import com.sky.pojo.dto.EmployeePageQueryDTO;
|
||||||
|
@ -18,9 +15,6 @@ import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 员工管理
|
* 员工管理
|
||||||
*/
|
*/
|
||||||
|
@ -29,31 +23,14 @@ import java.util.Map;
|
||||||
@Slf4j
|
@Slf4j
|
||||||
@Api(tags = "员工相关接口")
|
@Api(tags = "员工相关接口")
|
||||||
public class EmployeeController {
|
public class EmployeeController {
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private EmployeeService employeeService;
|
private EmployeeService employeeService;
|
||||||
@Autowired
|
|
||||||
private JwtProperties jwtProperties;
|
|
||||||
|
|
||||||
@PostMapping("/login")
|
@PostMapping("/login")
|
||||||
@ApiOperation(value = "登录接口")
|
@ApiOperation(value = "登录接口")
|
||||||
public Result<EmployeeLoginVO> login(@RequestBody EmployeeLoginDTO employeeLoginDTO) {
|
public Result<EmployeeLoginVO> login(@RequestBody EmployeeLoginDTO employeeLoginDTO) {
|
||||||
log.info("员工登录:{}", employeeLoginDTO);
|
log.info("员工登录:{}", employeeLoginDTO);
|
||||||
|
return Result.success(employeeService.login(employeeLoginDTO));
|
||||||
Employee employee = employeeService.login(employeeLoginDTO);
|
|
||||||
|
|
||||||
// 登录成功后,生成jwt令牌
|
|
||||||
Map<String, Object> claims = new HashMap<>();
|
|
||||||
claims.put(JwtClaimsConstant.EMP_ID, employee.getId());
|
|
||||||
String token = JwtUtil.createJWT(jwtProperties.getAdminSecretKey(), jwtProperties.getAdminTtl(), claims);
|
|
||||||
|
|
||||||
EmployeeLoginVO employeeLoginVO = EmployeeLoginVO.builder()
|
|
||||||
.id(employee.getId())
|
|
||||||
.userName(employee.getUsername())
|
|
||||||
.name(employee.getName())
|
|
||||||
.token(token).build();
|
|
||||||
|
|
||||||
return Result.success(employeeLoginVO);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping("/logout")
|
@PostMapping("/logout")
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
package com.sky.controller.user;
|
package com.sky.controller.user;
|
||||||
|
|
||||||
import com.sky.common.constant.JwtClaimsConstant;
|
import com.sky.common.constant.JwtClaimsConstant;
|
||||||
import com.sky.common.properties.JwtProperties;
|
import com.sky.common.properties.RedisTokenProperties;
|
||||||
import com.sky.common.result.Result;
|
import com.sky.common.result.Result;
|
||||||
import com.sky.common.utils.JwtUtil;
|
import com.sky.common.utils.JwtUtil;
|
||||||
import com.sky.pojo.dto.UserLoginDTO;
|
import com.sky.pojo.dto.UserLoginDTO;
|
||||||
|
@ -28,7 +28,7 @@ public class UserController {
|
||||||
@Autowired
|
@Autowired
|
||||||
private UserService userService;
|
private UserService userService;
|
||||||
@Autowired
|
@Autowired
|
||||||
private JwtProperties jwtProperties;
|
private RedisTokenProperties redisTokenProperties;
|
||||||
|
|
||||||
@PostMapping("/login")
|
@PostMapping("/login")
|
||||||
@ApiOperation("微信登录")
|
@ApiOperation("微信登录")
|
||||||
|
@ -41,7 +41,7 @@ public class UserController {
|
||||||
// 为微信用户生成jwt令牌
|
// 为微信用户生成jwt令牌
|
||||||
Map<String, Object> claims = new HashMap<>();
|
Map<String, Object> claims = new HashMap<>();
|
||||||
claims.put(JwtClaimsConstant.USER_ID, user.getId());
|
claims.put(JwtClaimsConstant.USER_ID, user.getId());
|
||||||
String token = JwtUtil.createJWT(jwtProperties.getUserSecretKey(), jwtProperties.getUserTtl(), claims);
|
String token = JwtUtil.createJWT(redisTokenProperties.getUserSecretKey(), redisTokenProperties.getUserTtl(), claims);
|
||||||
|
|
||||||
UserLoginVO userLoginVO = UserLoginVO.builder()
|
UserLoginVO userLoginVO = UserLoginVO.builder()
|
||||||
.id(user.getId())
|
.id(user.getId())
|
||||||
|
|
|
@ -7,6 +7,7 @@ import com.sky.pojo.dto.EmployeeLoginDTO;
|
||||||
import com.sky.pojo.dto.EmployeePageQueryDTO;
|
import com.sky.pojo.dto.EmployeePageQueryDTO;
|
||||||
import com.sky.pojo.dto.PasswordEditDTO;
|
import com.sky.pojo.dto.PasswordEditDTO;
|
||||||
import com.sky.pojo.entity.Employee;
|
import com.sky.pojo.entity.Employee;
|
||||||
|
import com.sky.pojo.vo.EmployeeLoginVO;
|
||||||
|
|
||||||
public interface EmployeeService {
|
public interface EmployeeService {
|
||||||
|
|
||||||
|
@ -16,7 +17,7 @@ public interface EmployeeService {
|
||||||
* @param employeeLoginDTO 员工等了信息
|
* @param employeeLoginDTO 员工等了信息
|
||||||
* @return 员工信息
|
* @return 员工信息
|
||||||
*/
|
*/
|
||||||
Employee login(EmployeeLoginDTO employeeLoginDTO);
|
EmployeeLoginVO login(EmployeeLoginDTO employeeLoginDTO);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 新增员工
|
* 新增员工
|
||||||
|
|
|
@ -16,21 +16,25 @@ import com.sky.pojo.dto.EmployeeLoginDTO;
|
||||||
import com.sky.pojo.dto.EmployeePageQueryDTO;
|
import com.sky.pojo.dto.EmployeePageQueryDTO;
|
||||||
import com.sky.pojo.dto.PasswordEditDTO;
|
import com.sky.pojo.dto.PasswordEditDTO;
|
||||||
import com.sky.pojo.entity.Employee;
|
import com.sky.pojo.entity.Employee;
|
||||||
|
import com.sky.pojo.vo.EmployeeLoginVO;
|
||||||
import com.sky.service.EmployeeService;
|
import com.sky.service.EmployeeService;
|
||||||
import org.springframework.beans.BeanUtils;
|
import org.springframework.beans.BeanUtils;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.data.redis.core.RedisTemplate;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.util.DigestUtils;
|
import org.springframework.util.DigestUtils;
|
||||||
|
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
@Service
|
@Service
|
||||||
public class EmployeeServiceImpl implements EmployeeService {
|
public class EmployeeServiceImpl implements EmployeeService {
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private EmployeeMapper employeeMapper;
|
private EmployeeMapper employeeMapper;
|
||||||
|
@Autowired
|
||||||
|
private RedisTemplate<Object, Long> redisTemplate;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 员工登录
|
* 员工登录
|
||||||
|
@ -38,7 +42,7 @@ public class EmployeeServiceImpl implements EmployeeService {
|
||||||
* @param employeeLoginDTO 员工登录时传递的数据模型
|
* @param employeeLoginDTO 员工登录时传递的数据模型
|
||||||
* @return 员工信息
|
* @return 员工信息
|
||||||
*/
|
*/
|
||||||
public Employee login(EmployeeLoginDTO employeeLoginDTO) {
|
public EmployeeLoginVO login(EmployeeLoginDTO employeeLoginDTO) {
|
||||||
String username = employeeLoginDTO.getUsername();
|
String username = employeeLoginDTO.getUsername();
|
||||||
String password = employeeLoginDTO.getPassword();
|
String password = employeeLoginDTO.getPassword();
|
||||||
|
|
||||||
|
@ -64,8 +68,16 @@ public class EmployeeServiceImpl implements EmployeeService {
|
||||||
throw new AccountLockedException(MessageConstant.ACCOUNT_LOCKED);
|
throw new AccountLockedException(MessageConstant.ACCOUNT_LOCKED);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO 生成token,使用userId存入登录信息
|
||||||
|
String token = UUID.randomUUID().toString();
|
||||||
|
String userId = employee.getId().toString();
|
||||||
|
redisTemplate.opsForValue().set(token, Long.valueOf(userId));
|
||||||
// 3、返回实体对象
|
// 3、返回实体对象
|
||||||
return employee;
|
return EmployeeLoginVO.builder()
|
||||||
|
.id(employee.getId())
|
||||||
|
.userName(employee.getUsername())
|
||||||
|
.name(employee.getName())
|
||||||
|
.token(token).build();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -0,0 +1,54 @@
|
||||||
|
package com.sky.task;
|
||||||
|
|
||||||
|
import com.sky.mapper.OrderMapper;
|
||||||
|
import com.sky.pojo.entity.Orders;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.scheduling.annotation.Scheduled;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
@Slf4j
|
||||||
|
public class OrderTask {
|
||||||
|
@Resource
|
||||||
|
private OrderMapper orderMapper;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理超时订单
|
||||||
|
*/
|
||||||
|
@Scheduled(cron = "0 * * * * ?")
|
||||||
|
// @Scheduled(cron = "0/5 * * * * ?")
|
||||||
|
public void processTImeOrder() {
|
||||||
|
log.info("定时处理超时订单:{}", LocalDateTime.now());
|
||||||
|
LocalDateTime time = LocalDateTime.now().plusMinutes(-15);
|
||||||
|
List<Orders> list = orderMapper.getByStatusAndOrderTime(Orders.PENDING_PAYMENT, time);
|
||||||
|
if (list != null && !list.isEmpty()) {
|
||||||
|
for (Orders orders : list) {
|
||||||
|
orders.setStatus(Orders.CANCELLED);
|
||||||
|
orders.setCancelReason("订单超时,自动取消");
|
||||||
|
orders.setCancelTime(LocalDateTime.now());
|
||||||
|
orderMapper.update(orders);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理一直派送中的订单
|
||||||
|
*/
|
||||||
|
@Scheduled(cron = "0 0 1 * * ?")
|
||||||
|
// @Scheduled(cron = "0/5 * * * * ?")
|
||||||
|
public void processDeliveryOrder() {
|
||||||
|
log.info("定时处理处于派送中的订单:{}", LocalDateTime.now());
|
||||||
|
LocalDateTime time = LocalDateTime.now().plusMinutes(-60);
|
||||||
|
List<Orders> list = orderMapper.getByStatusAndOrderTime(Orders.DELIVERY_IN_PROGRESS, time);
|
||||||
|
if (list != null && !list.isEmpty()) {
|
||||||
|
for (Orders orders : list) {
|
||||||
|
orders.setStatus(Orders.COMPLETED);
|
||||||
|
orderMapper.update(orders);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,20 @@
|
||||||
|
package com.sky.task;
|
||||||
|
|
||||||
|
import com.sky.websocket.WebSocketServer;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.scheduling.annotation.Scheduled;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.time.format.DateTimeFormatter;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
public class WebSocketTask {
|
||||||
|
@Autowired
|
||||||
|
WebSocketServer webSocketServer;
|
||||||
|
|
||||||
|
@Scheduled(cron = "0/2 * * * * ?")
|
||||||
|
public void sendMessageToClient() {
|
||||||
|
webSocketServer.sendToAllClient("这是来自服务端消息" + DateTimeFormatter.ofPattern("HH:mm:ss").format(LocalDateTime.now()));
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,47 @@
|
||||||
|
package com.sky.websocket;
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import javax.websocket.OnMessage;
|
||||||
|
import javax.websocket.OnOpen;
|
||||||
|
import javax.websocket.Session;
|
||||||
|
import javax.websocket.server.PathParam;
|
||||||
|
import javax.websocket.server.ServerEndpoint;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
@ServerEndpoint("/ws/{sid}")
|
||||||
|
@Slf4j
|
||||||
|
public class WebSocketServer {
|
||||||
|
// 存放会话对象
|
||||||
|
private static final Map<String, Session> sessionMap = new HashMap<>();
|
||||||
|
|
||||||
|
// 连接建立成功调用的方法
|
||||||
|
@OnOpen
|
||||||
|
public void onOpen(Session session, @PathParam("sid") String sid) {
|
||||||
|
log.info("客户端:{}--->建立连接", sid);
|
||||||
|
sessionMap.put(sid, session);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 收到客户端消息后调用的方法
|
||||||
|
@OnMessage
|
||||||
|
public void onMessage(String message, @PathParam("sid") String sid) {
|
||||||
|
log.info("收到来自客户端:{};信息为:{}", sid, message);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 群发
|
||||||
|
public void sendToAllClient(String message) {
|
||||||
|
Collection<Session> sessions = sessionMap.values();
|
||||||
|
for (Session session : sessions) {
|
||||||
|
try {
|
||||||
|
// 服务器向客户端发送消息
|
||||||
|
session.getBasicRemote().sendText(message);
|
||||||
|
} catch (Exception exception) {
|
||||||
|
exception.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -15,7 +15,7 @@ sky:
|
||||||
|
|
||||||
redis:
|
redis:
|
||||||
host: 106.15.251.123
|
host: 106.15.251.123
|
||||||
port: 6378
|
port: 6379
|
||||||
password: "02120212"
|
password: "02120212"
|
||||||
database: 10
|
database: 10
|
||||||
|
|
||||||
|
|
|
@ -37,9 +37,9 @@ logging:
|
||||||
controller: info
|
controller: info
|
||||||
|
|
||||||
sky:
|
sky:
|
||||||
jwt:
|
redisToken:
|
||||||
# 设置jwt签名加密时使用的秘钥
|
# 设置jwt签名加密时使用的秘钥
|
||||||
admin-secret-key: itcast
|
admin-secret-key: bunny
|
||||||
# 设置jwt过期时间
|
# 设置jwt过期时间
|
||||||
admin-ttl: 7200000
|
admin-ttl: 7200000
|
||||||
# 设置前端传递过来的令牌名称
|
# 设置前端传递过来的令牌名称
|
||||||
|
|
Loading…
Reference in New Issue