This commit is contained in:
Jerry Yan 2024-11-28 15:10:09 +08:00
commit 901691aaea
90 changed files with 4919 additions and 0 deletions

3
.gitignore vendored Normal file
View File

@ -0,0 +1,3 @@
.idea/
logs/
target/

8
.idea/.gitignore generated vendored Normal file
View File

@ -0,0 +1,8 @@
# 默认忽略的文件
/shelf/
/workspace.xml
# 基于编辑器的 HTTP 客户端请求
/httpRequests/
# Datasource local storage ignored files
/dataSources/
/dataSources.local.xml

19
.idea/compiler.xml generated Normal file
View File

@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="CompilerConfiguration">
<annotationProcessing>
<profile default="true" name="Default" enabled="true" />
<profile name="Maven default annotation processors profile" enabled="true">
<sourceOutputDir name="target/generated-sources/annotations" />
<sourceTestOutputDir name="target/generated-test-sources/test-annotations" />
<outputRelativeToContentRoot value="true" />
<module name="xinjiangshian" />
</profile>
</annotationProcessing>
</component>
<component name="JavacSettings">
<option name="ADDITIONAL_OPTIONS_OVERRIDE">
<module name="xinjiangshian" options="-parameters" />
</option>
</component>
</project>

6
.idea/encodings.xml generated Normal file
View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Encoding">
<file url="file://$PROJECT_DIR$/src/main/java" charset="UTF-8" />
</component>
</project>

25
.idea/jarRepositories.xml generated Normal file
View File

@ -0,0 +1,25 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="RemoteRepositoriesConfiguration">
<remote-repository>
<option name="id" value="central" />
<option name="name" value="Central Repository" />
<option name="url" value="https://repo.maven.apache.org/maven2" />
</remote-repository>
<remote-repository>
<option name="id" value="spring-milestones" />
<option name="name" value="Spring Milestones" />
<option name="url" value="https://repo.spring.io/milestone" />
</remote-repository>
<remote-repository>
<option name="id" value="central" />
<option name="name" value="Maven Central repository" />
<option name="url" value="https://repo1.maven.org/maven2" />
</remote-repository>
<remote-repository>
<option name="id" value="jboss.community" />
<option name="name" value="JBoss Community repository" />
<option name="url" value="https://repository.jboss.org/nexus/content/repositories/public/" />
</remote-repository>
</component>
</project>

12
.idea/misc.xml generated Normal file
View File

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ExternalStorageConfigurationManager" enabled="true" />
<component name="MavenProjectsManager">
<option name="originalFiles">
<list>
<option value="$PROJECT_DIR$/pom.xml" />
</list>
</option>
</component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" default="true" project-jdk-name="1.8" project-jdk-type="JavaSDK" />
</project>

6
.idea/vcs.xml generated Normal file
View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" />
</component>
</project>

0
README.md Normal file
View File

215
pom.xml Normal file
View File

@ -0,0 +1,215 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.12.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.ycwl</groupId>
<artifactId>basic</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>liuying</name>
<description>流影</description>
<properties>
<java.version>8</java.version>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<mybatisplus.boot.starter.version>3.4.0</mybatisplus.boot.starter.version>
<hutool-all.version>5.6.0</hutool-all.version>
<fastjson.version>1.2.76</fastjson.version>
<knife4j-spring-boot-starter.version>2.0.7</knife4j-spring-boot-starter.version>
<pagehelper.version>5.1.10</pagehelper.version>
<!--跳过单元测试-->
<skipTests>true</skipTests>
<!--log4j2bug问题-->
<log4j2.version>2.17.0</log4j2.version>
</properties>
<dependencies>
<!-- 引入aop相关 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<!--项目中添加 spring-boot-starter-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- 引入redis并且redis使用jedis连接 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
<exclusions>
<exclusion>
<groupId>io.lettuce</groupId>
<artifactId>lettuce-core</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
</dependency>
<!-- 引入mysql连接 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<!-- 引入springboot测试 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
</dependency>
<!--mybatis plus和springboot整合-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>${mybatisplus.boot.starter.version}</version>
</dependency>
<!-- 引入lombok工具 -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<!--<scope>provided</scope>-->
</dependency>
<!-- hutool工具类 -->
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>${hutool-all.version}</version>
</dependency>
<!-- hutool生成二维码利用Google的zixing-->
<dependency>
<groupId>com.google.zxing</groupId>
<artifactId>core</artifactId>
<version>3.3.3</version>
</dependency>
<!-- json处理工具 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>${fastjson.version}</version>
</dependency>
<!-- 引入commons-lang3 工具类 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>
<!-- 引入接口文档工具 -->
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-spring-boot-starter</artifactId>
<version>${knife4j-spring-boot-starter.version}</version>
</dependency>
<!-- pageHelper -->
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper</artifactId>
<version>${pagehelper.version}</version>
<exclusions>
<exclusion>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
</exclusion>
<exclusion>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- 引入jwt-->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.0</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-text</artifactId>
<version>1.1</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>
<!--钉钉-->
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>alibaba-dingtalk-service-sdk</artifactId>
<version>2.0.0</version>
</dependency>
<!-- &lt;!&ndash; mybatis-plus-generator 代码生成器依赖&ndash;&gt;-->
<!-- <dependency>-->
<!-- <groupId>com.baomidou</groupId>-->
<!-- <artifactId>mybatis-plus-generator</artifactId>-->
<!-- <version>3.3.1.tmp</version>-->
<!-- </dependency>-->
<!-- &lt;!&ndash; freemarker依赖&ndash;&gt;-->
<!-- <dependency>-->
<!-- <groupId>org.freemarker</groupId>-->
<!-- <artifactId>freemarker</artifactId>-->
<!-- </dependency>-->
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson</artifactId>
<version>3.14.1</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
<!-- 配置远程仓库 防止有时在阿里云找不到对应的jar包就去自带的spring.io拉取-->
<repositories>
<repository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/milestone</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
</project>

View File

@ -0,0 +1,15 @@
package com.ycwl.basic;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
@MapperScan(basePackages = "com.ycwl.basic.mapper")
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}

View File

@ -0,0 +1,21 @@
package com.ycwl.basic.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* ignore token validation
* <p>
* check all req except add this annotation
* this annotation could use in method and class type
* <p>
*
* @ahtuor yangchen
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(value = {ElementType.METHOD, ElementType.TYPE})
public @interface IgnoreToken {
}

View File

@ -0,0 +1,69 @@
package com.ycwl.basic.aspectj;
import com.alibaba.fastjson.JSON;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
/**
* @date 2022年10月13日 13:55
* 入参参数打印类
*/
@Aspect
@Component
public class RequestParameterAspectj {
private static final Logger LOGGER = LoggerFactory.getLogger(RequestParameterAspectj.class);
@Pointcut("execution(* com.ycwl.basic.controller.*.*.*(..))")
public void classPackage() {
}
@Around("classPackage()")
public Object parameterPoint(ProceedingJoinPoint joinPoint) throws Throwable {
final ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
if (requestAttributes != null) {
final HttpServletRequest request = requestAttributes.getRequest();
String requestURI = request.getRequestURI();
String method = request.getMethod();
HashSet<String> parameterValueSet = new HashSet<>();
Object[] requestParameterValue = joinPoint.getArgs();
for (Object o : requestParameterValue) {
if (!(o instanceof HttpServletRequest || o instanceof HttpServletResponse)) {
parameterValueSet.add(String.valueOf(o));
}
}
Enumeration<String> parameterNames = request.getParameterNames();
Map<String, String> parameterUrlMap = new HashMap<>();
while (parameterNames.hasMoreElements()) {
String parameterName = parameterNames.nextElement();
String parameterValue = request.getParameter(parameterName);
parameterUrlMap.put(parameterName, parameterValue);
}
if (parameterUrlMap.isEmpty()) {
LOGGER.info("当前请求的路径为-> {} 请求方式为-> {} 参数为-> {}", requestURI, method, JSON.toJSONString(parameterValueSet));
} else {
LOGGER.info("当前请求的路径为-> {} 请求方式为-> {} 参数为-> {} 路径传参为-> {}", requestURI, method,
JSON.toJSONString(parameterValueSet), JSON.toJSONString(parameterUrlMap));
}
}
return joinPoint.proceed();
}
}

View File

@ -0,0 +1,56 @@
package com.ycwl.basic.config;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializationContext;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import java.time.Duration;
/**
* @author wenshijia
* @date 2021年07月05日 18:34
* 修改redis缓存序列化器
*/
@Configuration
@EnableCaching
public class CustomRedisCacheManager extends CachingConfigurerSupport {
@Bean
public RedisCacheConfiguration redisCacheConfiguration() {
Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class);
RedisCacheConfiguration configuration = RedisCacheConfiguration.defaultCacheConfig();
configuration = configuration.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(jackson2JsonRedisSerializer)).entryTtl(Duration.ofMinutes(1));
return configuration;
}
/**
* 处理redis连接工具显示redis key值显示乱码问题value值没处理
*
* @param factory RedisConnectionFactory
* @return org.springframework.data.redis.core.RedisTemplate<java.lang.String, java.lang.Object>
* @date 2022/9/21 13:58
*/
@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
redisTemplate.setConnectionFactory(factory);
final StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
redisTemplate.setKeySerializer(stringRedisSerializer);
redisTemplate.setValueSerializer(stringRedisSerializer);
redisTemplate.setHashKeySerializer(stringRedisSerializer);
redisTemplate.afterPropertiesSet();
return redisTemplate;
}
}

View File

@ -0,0 +1,22 @@
package com.ycwl.basic.config;
import com.ycwl.basic.filter.XssFilter;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.servlet.DispatcherType;
@Configuration
public class FilterConfig {
@Bean
public FilterRegistrationBean xssFilterRegistrationBean(){
FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
filterRegistrationBean.setFilter(new XssFilter());
filterRegistrationBean.setOrder(1);
filterRegistrationBean.setDispatcherTypes(DispatcherType.REQUEST);
filterRegistrationBean.setEnabled(true);
filterRegistrationBean.addUrlPatterns("/*");
return filterRegistrationBean;
}
}

View File

@ -0,0 +1,32 @@
package com.ycwl.basic.config;
import com.baomidou.mybatisplus.annotation.DbType;
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 wenshijia
* @date 2021年06月04日 9:42
*/
@Configuration
public class MybatisPlusPageConfig {
/* 旧版本配置
@Bean
public PaginationInterceptor paginationInterceptor(){
return new PaginationInterceptor();
}*/
/**
* 新的分页插件,一缓和二缓遵循mybatis的规则,
* 需要设置 MybatisConfiguration#useDeprecatedExecutor = false 避免缓存出现问题
*/
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
return interceptor;
}
}

View File

@ -0,0 +1,26 @@
package com.ycwl.basic.config;
import com.github.pagehelper.PageInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.Properties;
/**
* @date 2022年05月18日 15:43
* PageHelper配置类
*/
@Configuration
public class PageHelperConfig {
@Bean(name = "pageHelper")
public PageInterceptor pageHelper() {
PageInterceptor pageHelper = new PageInterceptor();
Properties properties = new Properties();
properties.setProperty("reasonable", "false");
// 配置数据库的方言
properties.setProperty("helperDialect", "mysql");
pageHelper.setProperties(properties);
return pageHelper;
}
}

View File

@ -0,0 +1,50 @@
package com.ycwl.basic.config;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.jsontype.impl.LaissezFaireSubTypeValidator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import javax.annotation.Resource;
@Configuration
public class RedisConfig {
@Resource
private RedisConnectionFactory redisConnectionFactory;
@Bean
public RedisTemplate<Object, Object> redisTemplate() {
RedisTemplate<Object, Object> redisTemplate = new RedisTemplate<>();
redisTemplate.setConnectionFactory(redisConnectionFactory);
// 使用Jackson2JsonRedisSerialize 替换默认序列化
Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
objectMapper.activateDefaultTyping(LaissezFaireSubTypeValidator.instance, ObjectMapper.DefaultTyping.NON_FINAL);
jackson2JsonRedisSerializer.setObjectMapper(objectMapper);
// 设置value的序列化规则和 key的序列化规则
redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);
redisTemplate.setKeySerializer(new StringRedisSerializer());
redisTemplate.setHashKeySerializer(jackson2JsonRedisSerializer);
redisTemplate.setHashValueSerializer(jackson2JsonRedisSerializer);
redisTemplate.setDefaultSerializer(jackson2JsonRedisSerializer);
redisTemplate.setEnableDefaultSerializer(true);
redisTemplate.afterPropertiesSet();
return redisTemplate;
}
}

View File

@ -0,0 +1,31 @@
//package com.ycwl.basic.config;
//
//import org.redisson.Redisson;
//import org.redisson.api.RedissonClient;
//import org.redisson.config.Config;
//import org.springframework.beans.factory.annotation.Value;
//import org.springframework.context.annotation.Bean;
//import org.springframework.context.annotation.Configuration;
//
//@Configuration
//public class RedissonConfig {
//
// @Value("${spring.redis.host}")
// private String host;
// @Value("${spring.redis.port}")
// private String port;
// @Value("${spring.redis.password}")
// private String password;
//
// @Bean
// public RedissonClient getRedisSon() {
// Config config = new Config();
// String address = new StringBuilder("redis://").append(host).append(":").append(port).toString();
// config.useSingleServer().setAddress(address);
// if (null != password && !"".equals(password.trim())) {
// config.useSingleServer().setPassword(password);
// }
// return Redisson.create(config);
// }
//
//}

View File

@ -0,0 +1,72 @@
package com.ycwl.basic.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.ParameterBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.schema.ModelRef;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.Contact;
import springfox.documentation.service.Parameter;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2WebMvc;
import java.util.ArrayList;
import java.util.List;
/**
* Swagger 配置类
* 原生: /swagger-ui.html
* 美化: /doc.html
*/
@Configuration
@EnableSwagger2WebMvc
public class SwaggerConfig {
/**
* Swagger 实例 Bean Docket, 所以通过配置 Docket 实例来配置 Swagger
*/
@Bean
public Docket docket() {
return new Docket(DocumentationType.SWAGGER_2)
// 展示在 Swagger 页面上的自定义工程描述信息
.apiInfo(apiInfo())
// 选择展示哪些接口
.select()
//只有com.zcy.e.firstaid包内的才去展示
.apis(RequestHandlerSelectors.basePackage("com.ycwl"))
.paths(PathSelectors.any())
.build()
.globalOperationParameters(getGlobalRequestParameters());
}
/**
* Swagger 的描述信息
*/
public ApiInfo apiInfo() {
return new ApiInfoBuilder()
.title("city-investment-smart-park")
.description("城投智慧园区")
.contact(new Contact("ycwl", "www.xxx.com", "xxxxxxxxx.com"))
.version("1.0")
.build();
}
private List<Parameter> getGlobalRequestParameters() {
List<Parameter> parameters = new ArrayList<>();
parameters.add(new ParameterBuilder()
.name("token")
.description("登录令牌")
.parameterType("header")
.modelRef(new ModelRef("String"))
.required(true)
.build());
return parameters;
}
}

View File

@ -0,0 +1,118 @@
package com.ycwl.basic.config;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.ycwl.basic.interceptor.AuthInterceptor;
import com.ycwl.basic.xss.XssJacksonDeserializer;
import com.ycwl.basic.xss.XssJacksonSerializer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import java.util.List;
/**
* @date 2022年10月14日 11:20
*/
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
@Autowired
private AuthInterceptor authInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(authInterceptor)
// 拦截除指定接口外的所有请求通过判断 注解 来决定是否需要做登录验证
.addPathPatterns("/**")
.excludePathPatterns("/swagger-resources/**", "/webjars/**", "/v2/api-docs", "/doc.html/**", "/error", "/csrf", "/");
}
/**
* 配置静态资源
*/
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/static/**").addResourceLocations("classpath:/static/");
registry.addResourceHandler("/templates/**").addResourceLocations("classpath:/templates/");
/*放行swagger*/
registry.addResourceHandler("doc.html").addResourceLocations("classpath:/META-INF/resources/");
registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/");
}
/**
* attention:简单跨域就是GETHEAD和POST请求但是POST请求的"Content-Type"只能是application/x-www-form-urlencoded, multipart/form-data text/plain
* 反之就是非简单跨域此跨域有一个预检机制说直白点就是会发两次请求一次OPTIONS请求一次真正的请求
*/
@Bean
public CorsFilter corsFilter() {
final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
final CorsConfiguration config = new CorsConfiguration();
config.setAllowCredentials(true);
// 允许向该服务器提交请求的URI*表示全部允许在SpringMVC中如果设成*会自动转成当前请求头中的Origin
config.addAllowedOrigin("*");
// 允许访问的头信息,*表示全部
config.addAllowedHeader("*");
// 预检请求的缓存时间即在这个时间段里对于相同的跨域请求不会再预检了
config.setMaxAge(18000L);
// 允许提交请求的方法*表示全部允许
config.addAllowedMethod("OPTIONS");
config.addAllowedMethod("HEAD");
config.addAllowedMethod("GET");
config.addAllowedMethod("PUT");
config.addAllowedMethod("POST");
config.addAllowedMethod("DELETE");
config.addAllowedMethod("PATCH");
source.registerCorsConfiguration("/**", config);
return new CorsFilter(source);
}
@Bean
public WebMvcConfigurer createConvert() {
return new WebMvcConfigurer() {
@Override
public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder();
ObjectMapper mapper = builder.build();
/*注入自定义的序列化工具将RequestBody的参数进行转译后传输*/
SimpleModule simpleModule = new SimpleModule();
// XSS序列化
simpleModule.addSerializer(String.class, new XssJacksonSerializer());
simpleModule.addDeserializer(String.class, new XssJacksonDeserializer());
mapper.registerModule(simpleModule);
converters.add(new MappingJackson2HttpMessageConverter(mapper));
}
};
}
@Autowired
private StringHttpMessageConverter stringHttpMessageConverter;
@Autowired
private MappingJackson2HttpMessageConverter httpMessageConverter;
/**
* 添加转换器
*/
@Override
public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
for (int i = 0; i < converters.size(); i++) {
if (converters.get(i) instanceof StringHttpMessageConverter){
converters.set(i, stringHttpMessageConverter);
}
if (converters.get(i) instanceof MappingJackson2HttpMessageConverter) {
converters.set(i, httpMessageConverter);
}
}
}
}

View File

@ -0,0 +1,113 @@
package com.ycwl.basic.constant;
import com.ycwl.basic.utils.StringUtil;
import lombok.Data;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;
@Data
public class BaseContextHandler {
public static ThreadLocal<Map<String, Object>> threadLocal = new ThreadLocal();
public BaseContextHandler() {
}
public static void set(String key, Object value) {
Object map;
if ((map = (Map) threadLocal.get()) == null) {
map = new HashMap();
threadLocal.set((Map<String, Object>) map);
}
((Map) map).put(key, value);
}
public static Object get(String key) {
Object map;
if ((map = (Map) threadLocal.get()) == null) {
map = new HashMap();
threadLocal.set((Map<String, Object>) map);
}
return ((Map) map).get(key);
}
public static void setToken(String token) {
set("currentUserToken", token);
}
public static String getToken() {
return StringUtil.a(get("currentUserToken"));
}
public static String getAccount() {
return returnObjectValue(get("currentAccount"));
}
public static void setAccount(String userName) {
set("currentAccount", userName);
}
public static String getPhone() {
return returnObjectValue(get("currentPhone"));
}
public static void setPhone(String phone) {
set("currentPhone", phone);
}
public static String getName() {
return returnObjectValue(get("currentName"));
}
public static void setName(String name) {
set("currentName", name);
}
public static String getUserId() {
return returnObjectValue(get("currentUserId"));
}
public static void setUserId(String userId) {
set("currentUserId", userId);
}
public static String getRoleId() {
return get("currentRoleId").toString();
}
public static void setRoleId(String roleId) {
set("currentRoleId", roleId);
}
public static LocalDateTime getUserExpireTime() {
return (LocalDateTime) get("currentUserExpireTime");
}
public static void setUserExpireTime(LocalDateTime localDateTime) {
set("currentUserExpireTime", localDateTime);
}
/**
* 返回value
*
* @param value
* @return
*/
private static String returnObjectValue(Object value) {
return value == null ? null : value.toString();
}
/**
* 移除threadLocal
*/
public static void remove() {
threadLocal.remove();
}
}

View File

@ -0,0 +1,15 @@
package com.ycwl.basic.constant;
/**
* @date 2022年11月21日 10:17
* 公共的返回消息
*/
public class CommonReturnMessageConstant {
public static final String SAVE_SUCCESS = "保存成功";
public static final String SAVE_FAILED = "保存失败";
private CommonReturnMessageConstant() {
}
}

View File

@ -0,0 +1,21 @@
package com.ycwl.basic.constant;
/**
* @date 2022年11月21日 9:59
* 消费管理收费机是否绑定应用场所状态类
*/
public class ConsumeIsBindApplicationSiteConstant {
/**
* 未绑定
*/
public static final int UNBOUND = 0;
/**
* 已绑定
*/
public static final int BOUND = 1;
private ConsumeIsBindApplicationSiteConstant() {
}
}

View File

@ -0,0 +1,6 @@
package com.ycwl.basic.constant;
public class PermissionConstant {
public final static String USER_PERMISSION_URL = "userPermissionUrl:";
public final static String ROLE_STATUS = "roleStatus:";
}

View File

@ -0,0 +1,5 @@
package com.ycwl.basic.constant;
public class RequestConstant {
public final static String UPDATE_PASSWORD = "/api/adminUser/v1/updatePassword";
}

View File

@ -0,0 +1,18 @@
package com.ycwl.basic.constant;
public class ShareParkingSpaceRedisKeyConstant {
// 更改数量时候的锁
public final static String UPDATE_NUMBER_LOCK_KEY="ShareParking:updateNumberLockKey";
// 地上车位
public final static String GROUND_PARKING_SPACE_NUMBER="ShareParking:groundParkingSpaceNumber";
// 地下车位数
public final static String UNDERGROUND_PARKING_SPACE_NUMBER="ShareParking:undergroundParkingSpaceNumber";
// 每日开放预约时间
public final static String OPEN_TIME="ShareParking:openTime";
// 预约后当日车辆最晚停留时间
public final static String RESIDENCE_TIME="ShareParking:residenceTime";
//取消时间
public final static String CANCEL_TIME="ShareParking:cancelTime";
//支付时间
public final static String PAY_TIME="ShareParking:payTime";
}

View File

@ -0,0 +1,89 @@
package com.ycwl.basic.controller.pc;
import com.github.pagehelper.PageInfo;
import com.ycwl.basic.annotation.IgnoreToken;
import com.ycwl.basic.model.pc.adminUser.req.*;
import com.ycwl.basic.model.pc.adminUser.resp.AdminUserListRespVO;
import com.ycwl.basic.model.pc.adminUser.resp.StaffSimpleInfoRespVO;
import com.ycwl.basic.service.pc.AdminUserService;
import com.ycwl.basic.utils.ApiResponse;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@RestController
@RequestMapping("/api/adminUser/v1")
@Slf4j
@Api(tags = "系统后台用户管理")
public class AdminUserController {
@Autowired
AdminUserService adminUserService;
@PostMapping(value = "/login")
@ApiOperation(value = "登录")
@IgnoreToken
public ApiResponse login(@RequestBody LoginReqVO loginReqVO) throws Exception {
log.info("{}:开始登录管理后台", loginReqVO.getAccount());
return adminUserService.login(loginReqVO);
}
@PostMapping(value = "/updatePassword")
@ApiOperation(value = "用户自己修改密码")
public ApiResponse updatePassword(@RequestBody UpdatePasswordReqVO updatePasswordReqVO) throws Exception {
log.info("{}:开始修改管理后台密码", updatePasswordReqVO.getId());
return adminUserService.updatePassword(updatePasswordReqVO);
}
@PostMapping(value = "/list")
@ApiOperation(value = "系统后台用户列表")
//@IgnoreToken
public ApiResponse<PageInfo<List<AdminUserListRespVO>>> list(@RequestBody AdminUserListReqVO adminUserListReqVO) {
return adminUserService.list(adminUserListReqVO);
}
@PostMapping(value = "/query/list")
@ApiOperation(value = "系统后台用户列表查询")
@IgnoreToken
public ApiResponse<PageInfo<List<AdminUserListRespVO>>> queryList(@RequestBody AdminUserListReqVO adminUserListReqVO) {
return adminUserService.list(adminUserListReqVO);
}
@PostMapping(value = "/add")
@ApiOperation(value = "添加系统后台用户")
//@IgnoreToken
public ApiResponse add(@RequestBody AddOrUpdateAdminUserReqVO addOrUpdateAdminUserReqVO) {
return adminUserService.addOrUpdate(addOrUpdateAdminUserReqVO);
}
@PostMapping(value = "/update")
@ApiOperation(value = "更新系统后台用户")
//@IgnoreToken
public ApiResponse update(@RequestBody AddOrUpdateAdminUserReqVO addOrUpdateAdminUserReqVO) {
return adminUserService.addOrUpdate(addOrUpdateAdminUserReqVO);
}
@GetMapping(value = "/delete/{id}")
@ApiOperation(value = "删除")
//@IgnoreToken
public ApiResponse delete(@PathVariable("id") String id) {
return adminUserService.delete(id);
}
@PostMapping(value = "/resetPassword")
@ApiOperation(value = "重置密码")
//@IgnoreToken
public ApiResponse resetPassword(@RequestBody ResetPasswordReqVO resetPasswordReqVO) {
log.info("{}:开始重置后台密码", resetPasswordReqVO.getId());
return adminUserService.resetPassword(resetPasswordReqVO);
}
}

View File

@ -0,0 +1,67 @@
package com.ycwl.basic.controller.pc;
import com.github.pagehelper.PageInfo;
import com.ycwl.basic.annotation.IgnoreToken;
import com.ycwl.basic.model.pc.role.req.AddOrUpdateRoleReqVO;
import com.ycwl.basic.model.pc.role.req.RoleListReqVO;
import com.ycwl.basic.model.pc.role.resp.RoleListRespVO;
import com.ycwl.basic.service.pc.RoleService;
import com.ycwl.basic.utils.ApiResponse;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@RestController
@RequestMapping("/api/role/v1")
@Api(tags = "系统角色管理")
public class RoleController {
@Autowired
RoleService roleService;
@PostMapping(value = "/list")
@ApiOperation(value = "角色列表")
@IgnoreToken
public ApiResponse<PageInfo<List<RoleListRespVO>>> list(@RequestBody RoleListReqVO roleListReqVO) {
return roleService.list(roleListReqVO);
}
@PostMapping(value = "/addOrUpdate")
@ApiOperation(value = "添加或更新角色")
@IgnoreToken
public ApiResponse addOrUpdate(@RequestBody AddOrUpdateRoleReqVO addOrUpdateRoleReqVO) {
return roleService.addOrUpdate(addOrUpdateRoleReqVO);
}
@GetMapping(value = "/delete/{id}")
@ApiOperation(value = "删除")
@IgnoreToken
public ApiResponse delete(@PathVariable("id") String id) {
return roleService.delete(id);
}
@GetMapping(value = "/updateReturnMenu/{id}")
@ApiOperation(value = "编辑回显该角色当前菜单")
@IgnoreToken
public ApiResponse updateReturnMenu(@PathVariable("id") String id) {
return roleService.updateReturnMenu(id);
}
@GetMapping(value = "/menu/{type}")
@ApiOperation(value = " 菜单")
@IgnoreToken
public ApiResponse menu(@PathVariable("type") Integer type) {
return roleService.menu(type);
}
@GetMapping(value = "/updateStatus/{id}")
@ApiOperation(value = "更改角色类型状态")
//@IgnoreToken
public ApiResponse updateStatus(@PathVariable("id") String id) {
return roleService.updateStatus(id);
}
}

View File

@ -0,0 +1,36 @@
package com.ycwl.basic.enums;
import lombok.Getter;
import lombok.Setter;
/**
* @author songmingsong
* @since 2022-11-23
* 状态码定义
*/
public enum AppStatesCodeEnum {
/**
* 通用操作码
*/
USER_STATES_CODE(1),
UNKNOWN_MISTAKE(500, "未知错误"),
NO_STAFFINFO_ERROR(411, "员工信息不存在"),
;
@Getter
public int code;
@Getter
@Setter
public String message;
AppStatesCodeEnum(int code, String message) {
this.code = code;
this.message = message;
}
AppStatesCodeEnum(Integer statesCode) {
this.code = statesCode;
}
}

View File

@ -0,0 +1,41 @@
package com.ycwl.basic.enums;
import lombok.Getter;
import lombok.Setter;
/**
* @author wenshijia
* @date 2021年05月25日 22:29
* 状态码定义约束共6位数前三位代表服务后4位代表接口
* 比如 商品服务210,购物车是220用户服务230403代表权限
*/
public enum BizCodeEnum {
/**
* 通用操作码
*/
UNKNOWN_MISTAKE(500, "未知错误"),
VERIFY_CODE_ERROR(600, "验证码错误"),
NO_VERIFY_CODE_AUTH(700, "未进行授权"),
TOLL_MACHINE_BIND_APPLICATION_SITE(1000, "当前收费机已经绑定了应用场所"),
TOLL_MACHINE_EXIST(1001, "当前收费机编号已经存在"),
APPLICATION_SITE_EXIST(1002, "当前应用场所已经存在"),
CONFERENCE_DEVICE_EXIST(2001, "当前会议设设备已经存在"),
;
@Getter
public int code;
@Getter
@Setter
public String message;
BizCodeEnum(int code, String message) {
this.code = code;
this.message = message;
}
}

View File

@ -0,0 +1,27 @@
package com.ycwl.basic.exception;
import com.ycwl.basic.enums.AppStatesCodeEnum;
import lombok.Data;
/**
* @author songminsgong
* @since 2022-11-23
*/
@Data
public class AppException extends RuntimeException {
private Integer code;
private String msg;
public AppException(Integer code, String message) {
super(message);
this.code = code;
this.msg = message;
}
public AppException(AppStatesCodeEnum mobileCodeEnum) {
super(mobileCodeEnum.getMessage());
this.code = mobileCodeEnum.getCode();
this.msg = mobileCodeEnum.getMessage();
}
}

View File

@ -0,0 +1,38 @@
package com.ycwl.basic.exception;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
/**
* @author yangchen
*/
@Getter
@Setter
@NoArgsConstructor
public class BaseException extends RuntimeException {
private int status = 500;
public BaseException(String message, int status) {
super(message);
this.status = status;
}
public BaseException(String message) {
super(message);
}
public BaseException(String message, Throwable cause) {
super(message, cause);
}
public BaseException(Throwable cause) {
super(cause);
}
public BaseException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
super(message, cause, enableSuppression, writableStackTrace);
}
}

View File

@ -0,0 +1,27 @@
package com.ycwl.basic.exception;
import com.ycwl.basic.enums.BizCodeEnum;
import lombok.Data;
/**
* @author wenshijia
* @date 2021年05月25日 22:41
*/
@Data
public class BizException extends RuntimeException {
private Integer code;
private String msg;
public BizException(Integer code, String message) {
super(message);
this.code = code;
this.msg = message;
}
public BizException(BizCodeEnum bizCodeEnum) {
super(bizCodeEnum.getMessage());
this.code = bizCodeEnum.getCode();
this.msg = bizCodeEnum.getMessage();
}
}

View File

@ -0,0 +1,13 @@
package com.ycwl.basic.exception;
import com.ycwl.basic.utils.ApiConst;
public class CheckTokenException extends BaseException {
public CheckTokenException(String message) {
// 5003
super(message, ApiConst.Code.CODE_NO_SESSION.code());
}
}

View File

@ -0,0 +1,88 @@
package com.ycwl.basic.exception;
import com.ycwl.basic.enums.BizCodeEnum;
import com.ycwl.basic.utils.ApiResponse;
import org.apache.tomcat.util.http.fileupload.impl.SizeLimitExceededException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import javax.servlet.http.HttpServletResponse;
/**
* @date 2022年09月23日 10:19
* 全局异常处理器
*/
@RestControllerAdvice(basePackages = {"com.ycwl.smartPark"})
public class CustomExceptionHandle {
private static final Logger LOGGER = LoggerFactory.getLogger(CustomExceptionHandle.class);
@ExceptionHandler(CheckTokenException.class)
public ApiResponse tokenExceptionHandler(HttpServletResponse response, BaseException ex) {
response.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value());
return ApiResponse.buildResponse(200, ex.getMessage());
}
@ExceptionHandler(MissTokenException.class)
public ApiResponse tokenMissExceptionHandler(HttpServletResponse response, BaseException ex) {
response.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value());
return ApiResponse.buildResponse(ex.getStatus(), ex.getMessage());
}
@ExceptionHandler(TokenExpireException.class)
public ApiResponse tokenExpireException(HttpServletResponse response, BaseException ex) {
response.setStatus(HttpStatus.OK.value());
return ApiResponse.buildResponse(ex.getStatus(), ex.getMessage());
}
@ExceptionHandler(BaseException.class)
public ApiResponse baseExceptionHandler(HttpServletResponse response, BaseException ex) {
response.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value());
return ApiResponse.buildResponse(ex.getStatus(), ex.getMessage());
}
/**
* 自定义异常统一处理类
*/
@ExceptionHandler(value = BizException.class)
public ApiResponse<String> handle(BizException bizException) {
return ApiResponse.buildResponse(bizException.getCode(), bizException.getMsg());
}
/**
* 异常统一返回处理
*/
@ExceptionHandler(value = Exception.class)
public ApiResponse<String> handle(Exception e) {
LOGGER.error("系统异常 -> {}", e.getMessage(), e);
return ApiResponse.buildResult(BizCodeEnum.UNKNOWN_MISTAKE);
}
/**
* 移动端自定义异常统一处理类
*/
@ExceptionHandler(value = AppException.class)
public ApiResponse<String> handle(AppException appException) {
return ApiResponse.buildResponse(appException.getCode(), appException.getMsg());
}
/**
* 移动端自定义异常统一处理类
*/
@ExceptionHandler(value = HttpMessageNotReadableException.class)
public ApiResponse<String> handle(HttpMessageNotReadableException httpMessageNotReadableException) {
return ApiResponse.buildResponse(500, "请求参数格式错误");
}
/**
* 文件上传超长异常统一处理
*/
@ExceptionHandler(value = SizeLimitExceededException.class)
public ApiResponse<String> handle(SizeLimitExceededException sizeLimitExceededException) {
return ApiResponse.buildResponse(415, "文件过大,请重新上传");
}
}

View File

@ -0,0 +1,13 @@
package com.ycwl.basic.exception;
import com.ycwl.basic.utils.ApiConst;
public class MissTokenException extends BaseException {
public MissTokenException(String message) {
// 5003
super(message, ApiConst.Code.CODE_MISS_TOKEN_ERROR.code());
}
}

View File

@ -0,0 +1,11 @@
package com.ycwl.basic.exception;
import com.ycwl.basic.utils.ApiConst;
public class PermissionException extends BaseException{
public PermissionException(String message) {
// 5003
super(message, ApiConst.Code.CODE_COMMON_ERROR.code());
}
}

View File

@ -0,0 +1,11 @@
package com.ycwl.basic.exception;
import com.ycwl.basic.utils.ApiConst;
public class RoleStatusException extends BaseException{
public RoleStatusException(String message) {
// 5003
super(message, ApiConst.Code.CODE_COMMON_ERROR.code());
}
}

View File

@ -0,0 +1,14 @@
package com.ycwl.basic.exception;
import com.ycwl.basic.utils.ApiConst;
/**
* @author yangchen
*/
public class TokenExpireException extends BaseException {
public TokenExpireException(String message) {
// 5003
super(message, ApiConst.Code.CODE_NO_SESSION.code());
}
}

View File

@ -0,0 +1,33 @@
package com.ycwl.basic.filter;
import com.ycwl.basic.xss.XSSHttpServletRequestWrapper;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
public class XssFilter implements Filter {
/**
* 初始化方法
*/
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
/**
* 过滤方法
*/
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
ServletRequest wrapper = null;
if (request instanceof HttpServletRequest) {
HttpServletRequest servletRequest = (HttpServletRequest) request;
wrapper = new XSSHttpServletRequestWrapper(servletRequest);
}
if (null == wrapper) {
chain.doFilter(request, response);
} else {
chain.doFilter(wrapper, response);
}
}
}

View File

@ -0,0 +1,184 @@
package com.ycwl.basic.interceptor;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.ycwl.basic.annotation.IgnoreToken;
import com.ycwl.basic.constant.BaseContextHandler;
import com.ycwl.basic.constant.PermissionConstant;
import com.ycwl.basic.constant.RequestConstant;
import com.ycwl.basic.exception.CheckTokenException;
import com.ycwl.basic.exception.MissTokenException;
import com.ycwl.basic.exception.PermissionException;
import com.ycwl.basic.exception.TokenExpireException;
import com.ycwl.basic.model.jwt.JwtInfo;
import com.ycwl.basic.utils.JwtTokenUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
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.handler.HandlerInterceptorAdapter;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.List;
@Slf4j
@Component
public class AuthInterceptor extends HandlerInterceptorAdapter {
@Autowired
JwtTokenUtil jwtTokenUtil;
@Autowired
RedisTemplate redisTemplate;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
if (!(handler instanceof HandlerMethod)) {
return super.preHandle(request, response, handler);
}
String requestURI = request.getRequestURI();
HandlerMethod handlerMethod = (HandlerMethod) handler;
// 获取类上面的注解
IgnoreToken ignoreClassToken = handlerMethod.getBeanType().getAnnotation(IgnoreToken.class);
// 获取方法上的注解
IgnoreToken ignoreMethodToken = handlerMethod.getMethodAnnotation(IgnoreToken.class);
if (ignoreClassToken != null || ignoreMethodToken != null) {
// 放行
return super.preHandle(request, response, handler);
}
// 放行白名单
if (getWhite(request.getRequestURI())) {
return true;
}
/*
验证token
*/
// 获取 token
String token = getToken(request);
if (StringUtils.isEmpty(token)) {
log.error("==> 请求 header 缺少 Token [{}]", token);
throw new MissTokenException("请求头缺少token");
}
// 解析 token & 验证 token 有效期
JwtInfo jwtInfo;
try {
jwtInfo = jwtTokenUtil.parsingToken(token);
log.info("用户信息:" + jwtInfo.toString());
LocalDateTime expireTime = jwtInfo.getExpireTime();
if (LocalDateTime.now(ZoneId.systemDefault()).isAfter(expireTime)) {
throw new TokenExpireException("token过期");
}
BaseContextHandler.setToken(token);
BaseContextHandler.setName(jwtInfo.getName());
BaseContextHandler.setUserId(jwtInfo.getUserId());
BaseContextHandler.setAccount(jwtInfo.getAccount());
BaseContextHandler.setPhone(jwtInfo.getPhone());
BaseContextHandler.setRoleId(jwtInfo.getRoleId());
BaseContextHandler.setUserExpireTime(jwtInfo.getExpireTime());
} catch (CheckTokenException e) {
throw new CheckTokenException("token无效");
}
// if (getBusinessWhite(requestURI)) {
// if (!getPermission(jwtInfo.getRoleId(), requestURI)) {
// throw new PermissionException("无权访问");
// }
// }
return true;
}
public static void sendJsonMessage(HttpServletResponse response, Object obj) {
ObjectMapper objectMapper = new ObjectMapper();
response.setContentType("application/json; charset=utf-8");
try (PrintWriter writer = response.getWriter()) {
writer.print(objectMapper.writeValueAsString(obj));
response.flushBuffer();
} catch (IOException e) {
log.warn("响应json数据给前端异常 -> {}", e.getMessage(), e);
}
}
/**
* 在请求完全结束后调用, 常用于清理资源等工作
*/
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
BaseContextHandler.remove();
super.afterCompletion(request, response, handler, ex);
}
public String getToken(HttpServletRequest request) {
String token = request.getHeader("token");
if (StringUtils.isEmpty(token)) {
if (request.getCookies() != null) {
for (Cookie cookie : request.getCookies()) {
if (("token").equals(cookie.getName())) {
token = cookie.getValue();
}
}
}
}
return token;
}
//白名单swagger2
private boolean getWhite(String path) {
return StringUtils.containsAny(
path,
"springfox", "swagger", "v2",
"webjars", "doc.html", "favicon.ico"
);
}
/**
* 业务接口白名单
*
* @param
* @return
*/
private boolean getBusinessWhite(String path) {
if (path.contains(RequestConstant.UPDATE_PASSWORD)) {
return false;
}
return true;
}
private boolean getPermission(String roleId, String url) {
Object permissionUrl = redisTemplate.opsForValue().get(PermissionConstant.USER_PERMISSION_URL + roleId);
if (permissionUrl != null) {
List<String> permissionUrlList = (List<String>) permissionUrl;
String urlWithParameters = url.substring(url.lastIndexOf("/") + 1, url.length());
boolean flag = StringUtils.isNumeric(urlWithParameters);
if (flag) {
url = url.substring(0, url.lastIndexOf("/"));
}
for (String str : permissionUrlList) {
if (str.equals(url)) {
return true;
}
}
}
return false;
}
}

View File

@ -0,0 +1,28 @@
package com.ycwl.basic.mapper.pc;
import com.ycwl.basic.model.pc.adminUser.entity.LoginEntity;
import com.ycwl.basic.model.pc.adminUser.req.AddOrUpdateAdminUserReqVO;
import com.ycwl.basic.model.pc.adminUser.req.AdminUserListReqVO;
import com.ycwl.basic.model.pc.adminUser.req.ResetPasswordReqVO;
import com.ycwl.basic.model.pc.adminUser.req.UpdatePasswordReqVO;
import com.ycwl.basic.model.pc.adminUser.resp.AdminUserListRespVO;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
@Mapper
public interface AdminUserMapper {
List<AdminUserListRespVO> list(AdminUserListReqVO adminUserListReqVO);
int delete(String id);
int resetPassword(ResetPasswordReqVO resetPasswordReqVO);
int add(AddOrUpdateAdminUserReqVO addOrUpdateAdminUserReqVO);
int update(AddOrUpdateAdminUserReqVO addOrUpdateAdminUserReqVO);
LoginEntity login(@Param("account")String account);
int updatePassword(UpdatePasswordReqVO updatePasswordReqVO);
String getPasswordByAccount(@Param("id")String id);
}

View File

@ -0,0 +1,15 @@
package com.ycwl.basic.mapper.pc;
import com.ycwl.basic.model.pc.menu.MenuNode;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
@Mapper
public interface MenuMapper {
int delete(@Param("id")String id);
int addRoleMenu(@Param("id")String id,@Param("list") List<Integer> list);
List<MenuNode>getListByType(@Param("type")Integer type);
}

View File

@ -0,0 +1,24 @@
package com.ycwl.basic.mapper.pc;
import com.ycwl.basic.model.pc.menu.MenuNode;
import com.ycwl.basic.model.pc.role.req.AddOrUpdateRoleReqVO;
import com.ycwl.basic.model.pc.role.req.RoleListReqVO;
import com.ycwl.basic.model.pc.role.resp.RoleListRespVO;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
@Mapper
public interface RoleMapper {
List<RoleListRespVO> list(RoleListReqVO roleListReqVO);
int delete(String id);
int add(AddOrUpdateRoleReqVO addOrUpdateRoleReqVO);
int update(AddOrUpdateRoleReqVO addOrUpdateRoleReqVO);
List<MenuNode> getMenuById(@Param("id")String id);
int updateStatus(@Param("id")String id);
int getRoleStatus(@Param("id")String id);
}

View File

@ -0,0 +1,19 @@
package com.ycwl.basic.model.common;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
/**
* @date 2021年10月26日 14:09
*/
@ApiModel(value = "公共查询参数实体类", description = "公共查询参数实体类")
@Data
public class BaseQueryParameterReq {
@ApiModelProperty(value = "当前页数")
private Integer page = 1;
@ApiModelProperty(value = "每页条数")
private Integer pageSize = 10;
}

View File

@ -0,0 +1,55 @@
package com.ycwl.basic.model.jwt;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;
import java.io.Serializable;
import java.time.LocalDateTime;
/**
* @author yangchen
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
@ToString
public class JwtInfo implements Serializable {
private static final long serialVersionUID = 5452605590172369563L;
/**
* 用户名称
*/
private String name;
/**
* 用户ID
*/
private String userId;
/**
* 角色ID
*/
private String roleId;
/**
* 用户账号
*/
private String account;
private String phone;
/**
* 生成 token 的时间
* <p>
* 会加一个 expire 作为 token 的有效期
*/
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private LocalDateTime expireTime;
}

View File

@ -0,0 +1,9 @@
package com.ycwl.basic.model.pc.adminUser.entity;
import lombok.Data;
@Data
public class GetTokenReqVO {
private String account;
private String password;
}

View File

@ -0,0 +1,13 @@
package com.ycwl.basic.model.pc.adminUser.entity;
import lombok.Data;
@Data
public class LoginEntity {
private String staffId;
private String staffName;
private String account;
private String password;
private String roleId;
private String typeName;
}

View File

@ -0,0 +1,19 @@
package com.ycwl.basic.model.pc.adminUser.req;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@Data
@ApiModel(value = "新增或更新后台管理人员VO")
public class AddOrUpdateAdminUserReqVO {
@ApiModelProperty(value = "id有为更新没有为新增")
private String id;
@ApiModelProperty(value = "角色ID")
private String roleId;
@ApiModelProperty(value = "账号")
private String account;
@ApiModelProperty(value = "密码")
private String password;
}

View File

@ -0,0 +1,23 @@
package com.ycwl.basic.model.pc.adminUser.req;
import com.ycwl.basic.model.common.BaseQueryParameterReq;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@Data
@ApiModel(value = "后台管理人员请求VO")
public class AdminUserListReqVO extends BaseQueryParameterReq {
@ApiModelProperty(value = "姓名")
private String name;
@ApiModelProperty(value = "账号")
private String phone;
@ApiModelProperty(value = "工号")
private String jobNo;
@ApiModelProperty(value = "组织ID")
private String companyId;
//@ApiModelProperty(value = "部门ID")
//private String departmentId;
@ApiModelProperty(value = "角色ID")
private String roleId;
}

View File

@ -0,0 +1,14 @@
package com.ycwl.basic.model.pc.adminUser.req;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@Data
@ApiModel(value = "登录请求VO")
public class LoginReqVO {
@ApiModelProperty(value = "账号")
private String account;
@ApiModelProperty(value = "密码")
private String password;
}

View File

@ -0,0 +1,14 @@
package com.ycwl.basic.model.pc.adminUser.req;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@Data
@ApiModel(value = "重置密码请求VO")
public class ResetPasswordReqVO {
@ApiModelProperty(value = "id")
private String id;
@ApiModelProperty(value = "密码")
private String password;
}

View File

@ -0,0 +1,16 @@
package com.ycwl.basic.model.pc.adminUser.req;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@Data
@ApiModel(value = "")
public class UpdatePasswordReqVO {
@ApiModelProperty(value = "id",hidden = true)
private String id;
@ApiModelProperty(value = "密码")
private String pwd;
@ApiModelProperty(value = "新密码")
private String newPwd;
}

View File

@ -0,0 +1,28 @@
package com.ycwl.basic.model.pc.adminUser.resp;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@Data
@ApiModel(value = "后台管理人员返回列表VO")
public class AdminUserListRespVO {
@ApiModelProperty(value = "id")
private String id;
@ApiModelProperty(value = "员工ID")
private String staffId;
@ApiModelProperty(value = "员工姓名")
private String staffName;
@ApiModelProperty(value = "手机号")
private String phone;
@ApiModelProperty(value = "工号")
private String jobNo;
@ApiModelProperty(value = "组织")
private String companyName;
@ApiModelProperty(value = "组织ID")
private String companyId;
@ApiModelProperty(value = "角色")
private String roleName;
@ApiModelProperty(value = "角色ID")
private String roleId;
}

View File

@ -0,0 +1,22 @@
package com.ycwl.basic.model.pc.adminUser.resp;
import com.ycwl.basic.model.pc.menu.MenuNode;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.List;
@Data
@ApiModel(value = "登录返回VO")
public class LoginRespVO {
@ApiModelProperty(value = "token")
private String token;
@ApiModelProperty(value = "用户名")
private String name;
@ApiModelProperty(value = "角色名")
private String typeName;
@ApiModelProperty(value = "菜单列表")
private List<MenuNode> menuNodeList;
}

View File

@ -0,0 +1,16 @@
package com.ycwl.basic.model.pc.adminUser.resp;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@Data
@ApiModel(value = "员工信息返回VO")
public class StaffSimpleInfoRespVO {
@ApiModelProperty(value = "id")
private String id;
@ApiModelProperty(value = "名字")
private String name;
@ApiModelProperty(value = "工号")
private String jobNo;
}

View File

@ -0,0 +1,35 @@
package com.ycwl.basic.model.pc.menu;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.List;
/**
* @date 2022年10月20日 10:59
* 菜单数node类
*/
@Data
@ApiModel(value = "菜单数node类", description = "菜单数node类")
public class MenuNode {
@ApiModelProperty(value = "当前节点ID")
private String id;
@ApiModelProperty(value = "父节点ID")
private String parentId;
@ApiModelProperty(value = "菜单名")
private String name;
@ApiModelProperty(value = "路由")
private String target;
@ApiModelProperty(value = "排序")
private Integer sort;
@ApiModelProperty(value = "子节点数据")
private List<MenuNode> childrenList;
}

View File

@ -0,0 +1,19 @@
package com.ycwl.basic.model.pc.role.req;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.List;
@Data
public class AddOrUpdateRoleReqVO {
@ApiModelProperty(value = "id,更新的时候传")
private String id;
@ApiModelProperty(value = "角色名称")
private String name;
@ApiModelProperty(value = "0系统角色 1业务角色")
private Integer type;
@ApiModelProperty(value = "菜单ID列表")
private List<Integer> menuIdList;
}

View File

@ -0,0 +1,15 @@
package com.ycwl.basic.model.pc.role.req;
import com.ycwl.basic.model.common.BaseQueryParameterReq;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@Data
@ApiModel(value = "角色请求列表VO")
public class RoleListReqVO extends BaseQueryParameterReq {
@ApiModelProperty(value = "名字")
private String name;
@ApiModelProperty(value = "0系统角色 1业务角色")
private Integer type;
}

View File

@ -0,0 +1,20 @@
package com.ycwl.basic.model.pc.role.resp;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.Date;
@Data
@ApiModel(value = "角色列表返回数据VO")
public class RoleListRespVO {
@ApiModelProperty(value = "id")
private String id;
@ApiModelProperty(value = "名字")
private String name;
@ApiModelProperty(value = "0正常 1关闭")
private Integer status;
@ApiModelProperty(value = "创建时间")
private Date createTime;
}

View File

@ -0,0 +1,49 @@
package com.ycwl.basic.model.snowFlake;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
/**
* @author Created by liuhongguang on 2019年10月27日
* @Description
*/
@NoArgsConstructor
@AllArgsConstructor
@Data
public class UniqueId implements Serializable {
/**
* 0 + 41 + 5 + 5 + 12
* 固定 + 时间戳 + 工作机器ID + 数据中心ID + 序列号
*/
private static final long serialVersionUID = 8632670752020316524L;
/**
* 工作机器ID数据中心ID序列号上次生成ID的时间戳
*/
@ApiModelProperty(value = "机器ID")
private long machineId;
@ApiModelProperty(value = "数据中心ID")
private long datacenterId;
@ApiModelProperty(value = "毫秒内序列")
private long sequence;
@ApiModelProperty(value = "时间戳")
private long timestamp;
@Override
public String toString() {
return "UniqueIdRespVo{" +
"服务机器ID=" + machineId +
", 数据中心ID=" + datacenterId +
", 毫秒内的序列=" + sequence +
", 生成时间与预设时间戳间隔=" + timestamp +
'}';
}
}

View File

@ -0,0 +1,85 @@
package com.ycwl.basic.model.snowFlake;
import io.swagger.annotations.ApiModelProperty;
public class UniqueIdMetaData {
/**
* 取当前系统启动时间为参考起始时间
* 取1995-04-01为参考日
*/
// public static final long START_TIME = LocalDateTime.now().toInstant(ZoneOffset.UTC).toEpochMilli();
public static final long START_TIME = 796665600000L;
/**
* 机器ID所占位数
*/
@ApiModelProperty(value = "机器位数")
public static final long MACHINE_ID_BITS = 5L;
/**
* 机器ID最大值310-31
*/
@ApiModelProperty(value = "机器ID最大")
public static final long MAX_MACHINE_ID = ~(-1L << MACHINE_ID_BITS);
/**
* 数据中心ID所占位数
*/
@ApiModelProperty(value = "数据中心ID所占位数")
public static final long DATACENTER_ID_BITS = 5L;
/**
* 数据中心ID最大值310-31
*/
@ApiModelProperty(value = "数据中心ID最大值")
public static final long MAX_DATACENTER_ID = ~(-1L << MACHINE_ID_BITS);
/**
* Sequence所占位数
*/
@ApiModelProperty(value = "序列所占位数")
public static final long SEQUENCE_BITS = 12L;
/**
* 机器ID偏移量12
*/
@ApiModelProperty(value = "机器ID偏移量")
public static final long MACHINE_SHIFT_BITS = SEQUENCE_BITS;
/**
* 数据中心ID偏移量12+5=17
*/
@ApiModelProperty(value = "数据中心ID偏移量")
public static final long DATACENTER_SHIFT_BITS = SEQUENCE_BITS + MACHINE_ID_BITS;
/**
* 时间戳的偏移量12+5+5=22
*/
@ApiModelProperty(value = "时间戳偏移量")
public static final long TIMESTAMP_LEFT_SHIFT_BITS = SEQUENCE_BITS + MACHINE_ID_BITS + DATACENTER_ID_BITS;
/**
* Sequence掩码4095
*/
@ApiModelProperty(value = "序列掩码")
public static final long SEQUENCE_MASK = ~(-1L << SEQUENCE_BITS);
/**
* 机器ID掩码1023
*/
@ApiModelProperty(value = "机器ID掩码")
public static final long MACHINE_MASK = ~(-1L << MACHINE_ID_BITS);
/**
* 数据中心掩码1023
*/
@ApiModelProperty(value = "数据中心掩码")
public static final long DATACENTER_MASK = ~(-1L << MACHINE_ID_BITS);
/**
* 时间戳掩码2的41次方减1
*/
@ApiModelProperty(value = "时间戳掩码")
public static final long TIMESTAMP_MASK = ~(-1L << 41L);
}

View File

@ -0,0 +1,157 @@
package com.ycwl.basic.service.impl.pc;
import cn.hutool.crypto.digest.DigestUtil;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.ycwl.basic.constant.BaseContextHandler;
import com.ycwl.basic.exception.RoleStatusException;
import com.ycwl.basic.mapper.pc.AdminUserMapper;
import com.ycwl.basic.mapper.pc.RoleMapper;
import com.ycwl.basic.model.jwt.JwtInfo;
import com.ycwl.basic.model.pc.adminUser.entity.LoginEntity;
import com.ycwl.basic.model.pc.adminUser.req.*;
import com.ycwl.basic.model.pc.adminUser.resp.AdminUserListRespVO;
import com.ycwl.basic.model.pc.adminUser.resp.LoginRespVO;
import com.ycwl.basic.model.pc.menu.MenuNode;
import com.ycwl.basic.service.pc.AdminUserService;
import com.ycwl.basic.utils.ApiResponse;
import com.ycwl.basic.utils.JwtTokenUtil;
import com.ycwl.basic.utils.SnowFlakeUtil;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.List;
import static com.ycwl.basic.constant.PermissionConstant.ROLE_STATUS;
@Service
public class AdminUserServiceImpl implements AdminUserService {
@Autowired
AdminUserMapper adminUserMapper;
@Autowired
RoleMapper roleMapper;
@Autowired
JwtTokenUtil jwtTokenUtil;
@Autowired
RedisTemplate redisTemplate;
@Override
public ApiResponse list(AdminUserListReqVO adminUserListReqVO) {
PageHelper.startPage(adminUserListReqVO.getPage(), adminUserListReqVO.getPageSize());
List<AdminUserListRespVO> list = adminUserMapper.list(adminUserListReqVO);
PageInfo<AdminUserListRespVO> pageInfo = new PageInfo(list);
return ApiResponse.buildSuccessResponse(pageInfo);
}
@Override
public ApiResponse addOrUpdate(AddOrUpdateAdminUserReqVO addOrUpdateAdminUserReqVO) {
addOrUpdateAdminUserReqVO.setPassword(DigestUtil.md5Hex(addOrUpdateAdminUserReqVO.getPassword()));
String id = addOrUpdateAdminUserReqVO.getId();
if (StringUtils.isBlank(id)) {
addOrUpdateAdminUserReqVO.setId(SnowFlakeUtil.getId());
String password = addOrUpdateAdminUserReqVO.getPassword();
addOrUpdateAdminUserReqVO.setPassword(password);
int add = adminUserMapper.add(addOrUpdateAdminUserReqVO);
if (add > 0) {
return ApiResponse.buildSuccessResponse(null);
}
} else {
int update = adminUserMapper.update(addOrUpdateAdminUserReqVO);
if (update > 0) {
return ApiResponse.buildSuccessResponse(null);
}
}
return ApiResponse.buildCommonErrorResponse("失败");
}
@Override
public ApiResponse delete(String id) {
if (adminUserMapper.delete(id) > 0) {
return ApiResponse.buildSuccessResponse(null);
}
return ApiResponse.buildCommonErrorResponse("失败");
}
@Override
public ApiResponse resetPassword(ResetPasswordReqVO resetPasswordReqVO) {
resetPasswordReqVO.setPassword(DigestUtil.md5Hex(resetPasswordReqVO.getPassword()));
if (adminUserMapper.resetPassword(resetPasswordReqVO) > 0) {
return ApiResponse.buildSuccessResponse(null);
}
return ApiResponse.buildCommonErrorResponse("失败");
}
@Override
public ApiResponse login(LoginReqVO loginReqVO) throws Exception {
String account = loginReqVO.getAccount();
String password = loginReqVO.getPassword();
LoginEntity login = adminUserMapper.login(account);
if (login == null) {
return ApiResponse.buildCommonErrorResponse("账号不存在或密码错误");
}
if (!login.getPassword().equals(DigestUtil.md5Hex(password))) {
return ApiResponse.buildCommonErrorResponse("账号不存在或密码错误");
}
String roleId = login.getRoleId();
Object roleObject = redisTemplate.opsForValue().get(ROLE_STATUS + roleId);
if (roleObject != null) {
if (roleObject.toString().equals("1")) {
throw new RoleStatusException("该角色下的账号已被封禁,请联系管理员");
}
}
List<MenuNode> menuById = roleMapper.getMenuById(roleId);
List<MenuNode> MenuList = new ArrayList<>();
for (MenuNode item : menuById) {
if ("-1".equals(item.getParentId())) {
MenuList.add(item);
}
for (MenuNode item2 : menuById) {
if (item2.getParentId().equals(item.getId())) {
if (item.getChildrenList() == null) {
item.setChildrenList(new ArrayList<>());
}
item.getChildrenList().add(item2);
}
}
}
LoginRespVO loginRespVO = new LoginRespVO();
String token = jwtTokenUtil.generateToken(new JwtInfo(login.getStaffName(), login.getStaffId(), roleId, login.getAccount(), login.getAccount(), null));
loginRespVO.setToken(token);
loginRespVO.setName(login.getStaffName());
loginRespVO.setTypeName(login.getTypeName());
loginRespVO.setMenuNodeList(MenuList);
return ApiResponse.buildSuccessResponse(loginRespVO);
}
@Override
public ApiResponse updatePassword(UpdatePasswordReqVO updatePasswordReqVO) {
String userId = BaseContextHandler.getUserId();
updatePasswordReqVO.setId(userId);
String passwordByAccount = adminUserMapper.getPasswordByAccount(updatePasswordReqVO.getId());
String pwd = DigestUtil.md5Hex(updatePasswordReqVO.getPwd());
if (!passwordByAccount.equals(pwd)) {
return ApiResponse.buildCommonErrorResponse("密码错误!修改失败");
}
String newPwd = DigestUtil.md5Hex(updatePasswordReqVO.getNewPwd());
updatePasswordReqVO.setNewPwd(newPwd);
if (adminUserMapper.updatePassword(updatePasswordReqVO) > 0) {
return ApiResponse.buildSuccessResponse(null);
}
return ApiResponse.buildCommonErrorResponse("失败");
}
}

View File

@ -0,0 +1,131 @@
package com.ycwl.basic.service.impl.pc;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.ycwl.basic.mapper.pc.MenuMapper;
import com.ycwl.basic.mapper.pc.RoleMapper;
import com.ycwl.basic.model.pc.menu.MenuNode;
import com.ycwl.basic.model.pc.role.req.AddOrUpdateRoleReqVO;
import com.ycwl.basic.model.pc.role.req.RoleListReqVO;
import com.ycwl.basic.model.pc.role.resp.RoleListRespVO;
import com.ycwl.basic.service.pc.RoleService;
import com.ycwl.basic.utils.ApiResponse;
import com.ycwl.basic.utils.SnowFlakeUtil;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.List;
import static com.ycwl.basic.constant.PermissionConstant.ROLE_STATUS;
@Service
public class RoleServiceImpl implements RoleService {
@Autowired
RoleMapper roleMapper;
@Autowired
MenuMapper menuMapper;
@Autowired
RedisTemplate redisTemplate;
@Override
public ApiResponse list(RoleListReqVO roleListReqVO) {
PageHelper.startPage(roleListReqVO.getPage(),roleListReqVO.getPageSize());
if(roleListReqVO.getType()==null){
roleListReqVO.setType(0);
}
List<RoleListRespVO> list = roleMapper.list(roleListReqVO);
PageInfo<RoleListRespVO> pageInfo = new PageInfo(list);
return ApiResponse.buildSuccessResponse(pageInfo);
}
@Override
public ApiResponse addOrUpdate(AddOrUpdateRoleReqVO addOrUpdateRoleReqVO) {
String id = addOrUpdateRoleReqVO.getId();
if(StringUtils.isBlank(id)){
String roleId = SnowFlakeUtil.getId();
addOrUpdateRoleReqVO.setId(roleId);
if(roleMapper.add(addOrUpdateRoleReqVO)>0){
menuMapper.addRoleMenu(roleId,addOrUpdateRoleReqVO.getMenuIdList());
return ApiResponse.buildSuccessResponse(null);
}
}else {
if(roleMapper.update(addOrUpdateRoleReqVO)>0){
menuMapper.delete(addOrUpdateRoleReqVO.getId());
if(addOrUpdateRoleReqVO.getMenuIdList()!=null&addOrUpdateRoleReqVO.getMenuIdList().size()>0){
menuMapper.addRoleMenu(addOrUpdateRoleReqVO.getId(),addOrUpdateRoleReqVO.getMenuIdList());
}
return ApiResponse.buildSuccessResponse(null);
}
}
return ApiResponse.buildCommonErrorResponse("失败");
}
@Override
public ApiResponse delete(String id) {
if(roleMapper.delete(id)>0){
menuMapper.delete(id);
return ApiResponse.buildSuccessResponse(null);
}
return ApiResponse.buildCommonErrorResponse("失败");
}
@Override
public ApiResponse updateReturnMenu(String id) {
List<MenuNode> menuById = roleMapper.getMenuById(id);
List<MenuNode> MenuList = new ArrayList<>();
for (MenuNode item :menuById) {
if ("-1".equals(item.getParentId())) {
MenuList.add(item);
}
for (MenuNode item2 : menuById) {
if (item2.getParentId().equals(item.getId())) {
if (item.getChildrenList() == null) {
item.setChildrenList(new ArrayList<>());
}
item.getChildrenList().add(item2);
}
}
}
return ApiResponse.buildSuccessResponse(MenuList);
}
@Override
public ApiResponse menu(Integer type) {
if(type==null){
type=1;
}
List<MenuNode> listByType = menuMapper.getListByType(type);
List<MenuNode> MenuList = new ArrayList<>();
for (MenuNode item :listByType) {
if ("-1".equals(item.getParentId())) {
MenuList.add(item);
}
for (MenuNode item2 : listByType) {
if (item2.getParentId().equals(item.getId())) {
if (item.getChildrenList() == null) {
item.setChildrenList(new ArrayList<>());
}
item.getChildrenList().add(item2);
}
}
}
return ApiResponse.buildSuccessResponse(MenuList);
}
@Override
public ApiResponse updateStatus(String id) {
if(roleMapper.updateStatus(id)>0){
redisTemplate.opsForValue().set(ROLE_STATUS+id,roleMapper.getRoleStatus(id));
return ApiResponse.buildSuccessResponse(null);
}
return ApiResponse.buildCommonErrorResponse("失败");
}
}

View File

@ -0,0 +1,14 @@
package com.ycwl.basic.service.pc;
import com.ycwl.basic.model.pc.adminUser.req.*;
import com.ycwl.basic.utils.ApiResponse;
public interface AdminUserService {
ApiResponse list(AdminUserListReqVO adminUserListReqVO);
ApiResponse addOrUpdate(AddOrUpdateAdminUserReqVO addOrUpdateAdminUserReqVO);
ApiResponse delete(String id);
ApiResponse resetPassword(ResetPasswordReqVO resetPasswordReqVO);
ApiResponse login(LoginReqVO loginReqVO) throws Exception;
ApiResponse updatePassword(UpdatePasswordReqVO updatePasswordReqVO);
}

View File

@ -0,0 +1,4 @@
package com.ycwl.basic.service.pc;
public interface MerchantService {
}

View File

@ -0,0 +1,15 @@
package com.ycwl.basic.service.pc;
import com.ycwl.basic.model.pc.role.req.AddOrUpdateRoleReqVO;
import com.ycwl.basic.model.pc.role.req.RoleListReqVO;
import com.ycwl.basic.utils.ApiResponse;
public interface RoleService {
ApiResponse list(RoleListReqVO roleListReqVO);
ApiResponse addOrUpdate(AddOrUpdateRoleReqVO addOrUpdateRoleReqVO);
ApiResponse delete(String id);
ApiResponse updateReturnMenu(String id);
ApiResponse menu(Integer type);
ApiResponse updateStatus(String id);
}

View File

@ -0,0 +1,176 @@
//package com.ycwl.basic.task;
//
//
//import cn.hutool.core.util.StrUtil;
//import com.alibaba.fastjson.JSONArray;
//import com.alibaba.fastjson.JSONObject;
//import com.tu.common.redis.RedisUtils;
//import com.tu.common.utils.ChinaMobileUtil;
//import com.tu.common.utils.DateUtils;
//import com.tu.dao.TuSpaceManageDao;
//import com.tu.dto.GetLiveSteamUrlDTO;
//import lombok.extern.slf4j.Slf4j;
//import org.springframework.beans.factory.annotation.Autowired;
//import org.springframework.beans.factory.annotation.Value;
//import org.springframework.core.annotation.Order;
//import org.springframework.scheduling.annotation.EnableScheduling;
//import org.springframework.scheduling.annotation.Scheduled;
//import org.springframework.stereotype.Component;
//
//import javax.annotation.PostConstruct;
//import java.util.*;
//
//import static com.tu.common.utils.ChinaMobileUtil.getTokenBySend;
//import static com.tu.common.utils.ChinaMobileUtil.sendPost;
//
//@Slf4j
//@Component
//@EnableScheduling
//public class GetSpaceChinaMobileLiveSteamJob {
//
// @Autowired
// TuSpaceManageDao tuSpaceManageDao;
// @Autowired
// RedisUtils redisUtils;
// @Autowired
// ChinaMobileUtil chinaMobileUtil;
// @Value("${spring.profiles.active}")
// private String springProfile;
//
// //public static String token = null;
// private static Queue failMsgSubQueue = new LinkedList(); // 保存订阅失败的数据
//
// /**
// * 订阅消息
// */
// @PostConstruct
// public void msgSubscription() {
// new Thread(() -> {
// if (springProfile.equals("prod")) {
// List<GetLiveSteamUrlDTO> liveSteamUrl = tuSpaceManageDao.getLiveSteamUrl(null, 2);
// List<String> deviceIdList = new ArrayList<>();
// for (GetLiveSteamUrlDTO item : liveSteamUrl) {
// String deviceSn = item.getDeviceSn();
// if (deviceSn != null && !deviceSn.equals("")) {
// deviceIdList.add(deviceSn);
//
// if (deviceIdList.size() == 29) {
// // 30条数据为一组分开订阅
// String msg = doMsgSubscription(deviceIdList);
// if (StrUtil.isBlank(msg)) {
// // 消息订阅失败,过一会儿再试试
// List<String> failDeviceIdList = new ArrayList<>();
// Collections.copy(failDeviceIdList, deviceIdList);
// failMsgSubQueue.offer(failDeviceIdList);
// }
// deviceIdList = new ArrayList<>();
// }
//
// }
// }
// doMsgSubscription(deviceIdList);
// }
// }).start();
//
// }
//
//
// /**
// * 每小时扫描订阅失败的消息
// */
// @PostConstruct
// @Scheduled(cron = "0 0 * * * *")
// public void scanQueue() {
// if (failMsgSubQueue.size() > 0) {
// Object poll = failMsgSubQueue.poll();
// if (poll != null) {
// List<String> pollList = (List<String>) poll;
// String msg = doMsgSubscription(pollList);
// if (StrUtil.isBlank(msg)) {
// // 消息订阅失败,过一会儿再试试
// List<String> failDeviceIdList = new ArrayList<>();
// Collections.copy(failDeviceIdList, pollList);
// failMsgSubQueue.offer(failDeviceIdList);
// }
// }
// }
// }
//
//
// @PostConstruct
// @Scheduled(fixedRate = 1000 * 60 * 60 * 2)
// @Order(1)
// public void getToken() {
// if (springProfile.equals("prod")) {
// String tokenBySend = getTokenBySend();
// redisUtils.set("CHINA_MOBILE_TOKEN_KEY_NEW", tokenBySend, RedisUtils.HOUR_TOW_EXPIRE);
// }
// }
//
// @Scheduled(cron = "0 */19 * * * *")
// @PostConstruct
// @Order(2)
// public void setLiveSteam() {
// new Thread(() -> {
// if (springProfile.equals("prod")) {
// List<GetLiveSteamUrlDTO> liveSteamUrl = tuSpaceManageDao.getLiveSteamUrl(null, 2);
// for (GetLiveSteamUrlDTO item : liveSteamUrl) {
// String url = getLiveSteam(item.getDeviceSn());
// if (url != null && !url.equals("")) {
// tuSpaceManageDao.updateLiveSteamUrl(item.getId(), url);
// }
// }
// }
// }).start();
// }
//
// public String getLiveSteam(String deviceId) {
// log.info("【移动】开始获取视频流" + deviceId);
// String url_hls = "https://open.andmu.cn/v3/open/api/device/hls";
// JSONObject bodyParam = new JSONObject();
// bodyParam.put("deviceId", deviceId);
// bodyParam.put("endTime", DateUtils.addDateDays(new Date(), 2).getTime());
// log.info("【移动】bodyParam->{}", bodyParam);
// String res = sendPost(url_hls, bodyParam, chinaMobileUtil.getTempToken());
// log.info("【移动】开始获取视频流结果:-》{}" + res);
// JSONObject jsonObject = JSONObject.parseObject(res);
// String m3u8Url = null;
// if (jsonObject.get("resultCode").toString().equals("000000")) {
// String data = jsonObject.get("data").toString();
// JSONObject jsonData = JSONObject.parseObject(data);
// m3u8Url = jsonData.get("m3u8Url").toString();
// }
// // token已过期
// if (jsonObject.get("resultCode").toString().equals("11504")) {
// // 删除redis的token会重新获取
// redisUtils.delete("CHINA_MOBILE_TOKEN_KEY_NEW");
// getLiveSteam(deviceId);
// }
// return m3u8Url;
// }
//
//
// public static void main(String[] args) {
//
// //List<String> deviceIdList =new ArrayList<>(30);
// //deviceIdList.add("2");
// //deviceIdList.add("1");
// //
// //List<String> failDeviceIdList = new ArrayList<>(deviceIdList);
// //failMsgSubQueue.offer(failDeviceIdList);
// //deviceIdList = new ArrayList<>();
// //List<String> pollList = ( List<String>) failMsgSubQueue.poll();
// //for (String s : pollList) {
// // System.out.println(s);
// //}
// //System.out.println(failMsgSubQueue.poll());
// //System.out.println(failMsgSubQueue.size());
//
//
// //String s = doMsgSubscription(Arrays.asList("040312e7fc9f", "743fc2dae410"));
// //System.out.println(s);
// }
//
//
//
//}

View File

@ -0,0 +1,108 @@
package com.ycwl.basic.utils;
/**
* Api常量定义类
*
* @version 1.0.0
*/
public class ApiConst {
/**
* 返回CODE码定义, 按照httpstatus的code码定义, 系统自定义的为四位数
*
* @version 1.0.0
*/
public static enum Code {
/**
* 成功返回码
*/
CODE_SUCCESS_ZERO(0),
/**
* 成功返回码
*/
CODE_SUCCESS(200),
/**
* 返回内容为空
*/
CODE_CONTENT_EMPTY(204),
/**
* 访问被拒绝
*/
CODE_REJECT(403),
/**
* 无权限访问
*/
CODE_NO_AUTH(401),
/**
* 请求方法错误
*/
CODE_NOT_EXIST(404),
/**
* 请求版本错误
*/
CODE_VERSION_ERROR(406),
/**
* 获取锁错误
*/
CODE_GET_LOCK_ERROR(423),
/**
* 请求参数错误
*/
CODE_PARAM_ERROR(4001),
/**
* 服务器错误
*/
CODE_SERVER_ERROR(500),
/**
* 其他业务码定义
*/
CODE_COMMON_ERROR(5001),
/**
* 自动完成登录状态
*/
CODE_LOGIN_RETRY(5002),
/**
* 用户过期或处在无登录状态
*/
CODE_NO_SESSION(5003),
/**
* 请求第三方错误
*/
CODE_THIRDPARTY_ERROR(5004),
/**
* 检查异常
*/
CODE_CHECK_ERROR(5005),
/**
* 缺少TOKEN异常
*/
CODE_MISS_TOKEN_ERROR(5006);
private Code(int intCode) {
this.intCode = intCode;
}
private int intCode;
public int code() {
return intCode;
}
}
}

View File

@ -0,0 +1,193 @@
package com.ycwl.basic.utils;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.ycwl.basic.enums.BizCodeEnum;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import java.io.Serializable;
/**
* 所有接口返回数据的携带对象
*
* @param <T>
* @version 1.0.0
*/
@ApiModel(value = "通用返回数据对象")
public class ApiResponse<T> implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 返回CODE码详见{@link ApiConst.Code}中常量定义
*/
@ApiModelProperty(value = "状态码")
private int code;
/**
* 返回message
*/
@ApiModelProperty(value = "数据描述")
private String msg;
/**
* 成功返回数据
*/
@ApiModelProperty(value = "数据")
private T data;
public ApiResponse() {
}
/**
* 构建成功返回数据对象
*
* @param data 返回数据内容
* @return
*/
public static <T> ApiResponse<T> buildSuccessResponse(T data) {
ApiResponse<T> response = new ApiResponse<T>();
response.setCode(ApiConst.Code.CODE_SUCCESS.code());
response.setData(data);
return response;
}
/**
* 构建空返回对象
*
* @return
*/
public static <T> ApiResponse<T> buildEmptyResponse() {
ApiResponse<T> response = new ApiResponse<T>();
response.setCode(ApiConst.Code.CODE_CONTENT_EMPTY.code());
return response;
}
/**
* 构建常规错误返回对象
*
* @param msg
* @return
*/
public static <T> ApiResponse<T> buildCommonErrorResponse(String msg) {
return buildResponse(ApiConst.Code.CODE_COMMON_ERROR, msg);
}
/**
* 构建自定义CODE码对象
*
* @param code
* @param data
* @param msg
* @return
*/
public static <T> ApiResponse<T> buildResponse(int code, T data, String msg) {
ApiResponse<T> response = new ApiResponse<T>();
response.setCode(code);
response.setData(data);
response.setMsg(msg);
return response;
}
/**
* 根据返回值构建结果
*
* @param flag
* @param <T>
* @return
*/
public static <T> ApiResponse<T> buildFlagResponse(boolean flag, T data) {
ApiResponse<T> response = new ApiResponse<T>();
if (flag) {
response.setCode(ApiConst.Code.CODE_SUCCESS.code());
response.setData(data);
response.setMsg("成功");
return response;
}
response.setCode(ApiConst.Code.CODE_COMMON_ERROR.code());
response.setData(data);
response.setMsg("失败");
return response;
}
/**
* 构建CODE码和提示信息对象
*
* @param code
* @param msg
* @return
*/
public static <T> ApiResponse<T> buildResponse(ApiConst.Code code, String msg) {
ApiResponse<T> response = new ApiResponse<T>();
response.setCode(code.code());
response.setMsg(msg);
return response;
}
/**
* 构建用户自定义CODE码和提示信息对象
*
* @param code
* @param msg
* @return
*/
public static <T> ApiResponse<T> buildResponse(int code, String msg) {
ApiResponse<T> response = new ApiResponse<T>();
response.setCode(code);
response.setMsg(msg);
return response;
}
public static <T> ApiResponse<T> buildResult(BizCodeEnum bizCodeEnum) {
ApiResponse<T> apiResponse = new ApiResponse();
apiResponse.setCode(bizCodeEnum.code);
apiResponse.setMsg(bizCodeEnum.message);
return apiResponse;
}
/**
* 是否执行成功
*
* @return
*/
@JsonIgnore
public boolean isSuccess() {
return ApiConst.Code.CODE_SUCCESS.code() == this.code;
}
public int getCode() {
return code;
}
public void setCode(int code) {
this.code = code;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
@Override
public String toString() {
StringBuilder builder = new StringBuilder();
builder.append("[code=").append(code).append(", msg=").append(msg).append(", data=").append(data)
.append("]");
return builder.toString();
}
}

View File

@ -0,0 +1,44 @@
package com.ycwl.basic.utils;
import org.springframework.cglib.beans.BeanCopier;
import java.util.HashMap;
import java.util.Map;
/**
* @date 2022年03月09日 9:04
* @author wenshijia
* BeanCopier工具类
*/
public class BeanCopierUtils {
public static Map<String, BeanCopier> beanCopierCacheMap = new HashMap<>();
/**
*
* 将soruce对象的属性转换给target对象
* @date 2022/3/9 9:11
* @param source 需要转换的对象
* @param target 目标对象
*/
public static void copyProperties(Object source, Object target) {
BeanCopier beanCopier;
String cacheKey = source.getClass().toString() + target.getClass().toString();
if (!beanCopierCacheMap.containsKey(cacheKey)) {
synchronized (BeanCopierUtils.class) {
if (!beanCopierCacheMap.containsKey(cacheKey)) {
beanCopier = BeanCopier.create(source.getClass(), target.getClass(), false);
beanCopierCacheMap.put(cacheKey, beanCopier);
} else {
beanCopier = beanCopierCacheMap.get(cacheKey);
}
}
} else {
beanCopier = beanCopierCacheMap.get(cacheKey);
}
beanCopier.copy(source, target, null);
}
}

View File

@ -0,0 +1,137 @@
//package com.ycwl.smartPark.utils;
//
//import com.baomidou.mybatisplus.core.exceptions.MybatisPlusException;
//import com.baomidou.mybatisplus.core.toolkit.StringPool;
//import com.baomidou.mybatisplus.core.toolkit.StringUtils;
//import com.baomidou.mybatisplus.generator.AutoGenerator;
//import com.baomidou.mybatisplus.generator.InjectionConfig;
//import com.baomidou.mybatisplus.generator.config.*;
//import com.baomidou.mybatisplus.generator.config.po.TableInfo;
//import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
//import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine;
//
//import java.util.ArrayList;
//import java.util.List;
//import java.util.Scanner;
//
///**
// * 执行 main 方法控制台输入模块表名回车自动生成对应项目目录中
// *
// * @author songmingsong
// * @since 1.0.0
// */
//
//public class CodeGenerator {
//
// /**
// * <p>
// * 读取控制台内容
// * </p>
// */
// public static String scanner(String tip) {
// Scanner scanner = new Scanner(System.in);
// StringBuilder help = new StringBuilder();
// help.append("请输入" + tip + "");
// System.out.println(help.toString());
// if (scanner.hasNext()) {
// String ipt = scanner.next();
// if (StringUtils.isNotEmpty(ipt)) {
// return ipt;
// }
// }
// throw new MybatisPlusException("请输入正确的" + tip + "");
// }
//
// public static void main(String[] args) {
// // 代码生成器
// AutoGenerator mpg = new AutoGenerator();
//
// // 全局配置
// GlobalConfig gc = new GlobalConfig();
// String projectPath = System.getProperty("user.dir");
// // 生成到那个模块下
// gc.setOutputDir(projectPath + "/src/main/java");
// //作者
// gc.setAuthor("songmingsong");
// //打开输出目录
// gc.setOpen(false);
// //xml开启 BaseResultMap
// gc.setBaseResultMap(true);
// //xml 开启BaseColumnList
// gc.setBaseColumnList(true);
// // 实体属性 Swagger2 注解
// gc.setSwagger2(true);
// mpg.setGlobalConfig(gc);
//
// // 数据源配置
// DataSourceConfig dsc = new DataSourceConfig();
// dsc.setUrl("jdbc:mysql://49.4.2.89:3306/smart_park?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia" +
// "/Shanghai");
// dsc.setDriverName("com.mysql.cj.jdbc.Driver");
// dsc.setUsername("root");
// dsc.setPassword("yckj@2017");
// mpg.setDataSource(dsc);
//
// // 包配置
// PackageConfig pc = new PackageConfig();
// pc.setParent("com.ycwl.smartPark")
// .setEntity("model.app.notice.entity")
// .setMapper("mapper.app")
// .setService("service.app")
// .setServiceImpl("service.impl.app")
// .setController("controller.app");
// mpg.setPackageInfo(pc);
//
// // 自定义配置
// InjectionConfig cfg = new InjectionConfig() {
// @Override
// public void initMap() {
// // to do nothing
// }
// };
//
// // 如果模板引擎是 freemarker
// String templatePath = "/templates/mapper.xml.ftl";
// // 如果模板引擎是 velocity
// // String templatePath = "/templates/mapper.xml.vm";
//
// // 自定义输出配置
// List<FileOutConfig> focList = new ArrayList<>();
// // 自定义配置会被优先输出
// focList.add(new FileOutConfig(templatePath) {
// @Override
// public String outputFile(TableInfo tableInfo) {
// // 自定义输出文件名 如果你 Entity 设置了前后缀此处注意 xml 的名称会跟着发生变化
// return projectPath + "/src/main/resources/mapper/" + tableInfo.getEntityName() + "Mapper"
// + StringPool.DOT_XML;
// }
// });
// cfg.setFileOutConfigList(focList);
// mpg.setCfg(cfg);
//
// // 配置模板
// TemplateConfig templateConfig = new TemplateConfig();
//
// templateConfig.setXml(null);
// mpg.setTemplate(templateConfig);
//
// // 策略配置
// StrategyConfig strategy = new StrategyConfig();
// //数据库表映射到实体的命名策略
// strategy.setNaming(NamingStrategy.underline_to_camel);
// //数据库表字段映射到实体的命名策略
// strategy.setColumnNaming(NamingStrategy.no_change);
// //lombok模型
// strategy.setEntityLombokModel(true);
// //生成 @RestController 控制器
// strategy.setRestControllerStyle(true);
// strategy.setInclude(scanner("表名,多个英文逗号分割").split(","));
// strategy.setControllerMappingHyphenStyle(true);
// //表前缀
// strategy.setTablePrefix("t_");
// mpg.setStrategy(strategy);
// mpg.setTemplateEngine(new FreemarkerTemplateEngine());
// mpg.execute();
// }
//
//}

View File

@ -0,0 +1,186 @@
package com.ycwl.basic.utils;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.UUID;
import java.util.concurrent.ThreadLocalRandom;
/**
* @author wenshijia
* @date 2021年05月26日 23:02
*/
@Slf4j
public class CommonUtil {
/**
* 生成指定长度随机字母和数字
*/
private static final String ALL_CHAR_NUM = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
private static SecureRandom random;
static {
try {
random = SecureRandom.getInstance("SHA1PRNG");
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
}
/**
* 获取ip
*
* @param request
* @return
*/
public static String getIpAddr(HttpServletRequest request) {
String ipAddress = null;
try {
ipAddress = request.getHeader("x-forwarded-for");
if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {
ipAddress = request.getHeader("Proxy-Client-IP");
}
if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {
ipAddress = request.getHeader("WL-Proxy-Client-IP");
}
if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {
ipAddress = request.getRemoteAddr();
if ("127.0.0.1".equals(ipAddress)) {
// 根据网卡取本机配置的IP
InetAddress inet = null;
try {
inet = InetAddress.getLocalHost();
} catch (UnknownHostException e) {
e.printStackTrace();
}
ipAddress = inet.getHostAddress();
}
}
// 对于通过多个代理的情况第一个IP为客户端真实IP,多个IP按照','分割
if (ipAddress != null && ipAddress.length() > 15) {
// "***.***.***.***".length()
// = 15
if (ipAddress.indexOf(",") > 0) {
ipAddress = ipAddress.substring(0, ipAddress.indexOf(","));
}
}
} catch (Exception e) {
ipAddress = "";
}
return ipAddress;
}
/**
* md5加密
*
* @param data 需要加密的字符串
* @return java.lang.String
* @author wenshijia
* @date 2021/5/26 23:02
*/
public static String MD5(String data) {
try {
MessageDigest md = MessageDigest.getInstance("MD5");
byte[] array = md.digest(data.getBytes(StandardCharsets.UTF_8));
StringBuilder sb = new StringBuilder();
for (byte item : array) {
sb.append(Integer.toHexString((item & 0xFF) | 0x100).substring(1, 3));
}
return sb.toString().toUpperCase();
} catch (Exception exception) {
}
return null;
}
/**
* 生成随机数
*
* @param length 生成的随机数的长度
* @return java.lang.String
* @author wenshijia
* @date 2021/5/27 16:38
*/
public static String getRandomCode(int length) {
StringBuilder stringBuilder = new StringBuilder();
for (int i = 0; i < length; i++) {
stringBuilder.append(random.nextInt(10));
}
return stringBuilder.toString();
}
/**
* 获取当前时间的时间戳
*
* @return long
* @author wenshijia
* @date 2021/5/27 22:02
*/
public static long getCurrentTimestamp() {
return System.currentTimeMillis();
}
/**
* UUID生成
*
* @return java.lang.String
* @author wenshijia
* @date 2021/5/30 21:16
*/
public static String generateUUID() {
return UUID.randomUUID().toString().replace("-", "");
}
/**
* 生成指定长度随机字母和数字
*
* @param length 需要生成的字符串长度
* @return java.lang.String
* @author wenshijia
* @date 2021/5/31 16:43
*/
public static String getStringNumRandom(int length) {
ThreadLocalRandom random = ThreadLocalRandom.current();
//生成随机数字和字母,
StringBuilder saltString = new StringBuilder(length);
for (int i = 1; i <= length; ++i) {
saltString.append(ALL_CHAR_NUM.charAt(random.nextInt(ALL_CHAR_NUM.length())));
}
return saltString.toString();
}
/**
* @param response 返回response
* @param obj 返回的数据
* @author wenshijia
* @date 2021/6/2 21:11
*/
public static void sendJsonMessage(HttpServletResponse response, Object obj) {
ObjectMapper objectMapper = new ObjectMapper();
response.setContentType("application/json; charset=utf-8");
try (PrintWriter writer = response.getWriter()) {
writer.print(objectMapper.writeValueAsString(obj));
response.flushBuffer();
} catch (IOException e) {
log.warn("响应json数据给前端异常 -> {}", e.getMessage(), e);
}
}
}

View File

@ -0,0 +1,202 @@
package com.ycwl.basic.utils;
import java.math.BigDecimal;
import java.math.RoundingMode;
/**
* @date 2022年06月02日 13:40
* 自定义的BigDecimal计算工具类
*/
public class CustomBigDecimalUtils {
public static final BigDecimal HUNDRED_BIG_DECIMAL = new BigDecimal("100");
/**
* 除法
*
* @param divisor 除数
* @param dividend 被除数
* @param scale 保留的小数位数
* @param roundingMode 舍入模式比如四舍五入
* @return java.math.BigDecimal
* @date 2022/6/2 13:43
*/
public static BigDecimal divide(BigDecimal divisor,
BigDecimal dividend,
int scale,
RoundingMode roundingMode) {
if (divisor == null || dividend == null) {
throw new NullPointerException("传入的数据不能为空");
}
if (Double.compare(divisor.doubleValue(), BigDecimal.ZERO.doubleValue()) == 0 ||
Double.compare(dividend.doubleValue(), BigDecimal.ZERO.doubleValue()) == 0) {
return BigDecimal.ZERO;
}
return divisor.divide(dividend, scale, roundingMode);
}
/**
* 除法
*
* @param divisor 除数
* @param dividend 被除数
* @param scale 保留的小数位数
* @param roundingMode 舍入模式比如四舍五入
* @return java.math.BigDecimal
* @date 2022/6/2 13:43
*/
public static BigDecimal divide(Integer divisor,
Integer dividend,
int scale,
RoundingMode roundingMode) {
if (divisor == null || dividend == null) {
throw new NullPointerException("传入的数据不能为空");
}
if (divisor == 0 || dividend == 0) {
return BigDecimal.ZERO;
}
return new BigDecimal(divisor).divide(new BigDecimal(dividend), scale, roundingMode);
}
/**
* 除法
*
* @param divisor 除数
* @param dividend 被除数
* @param scale 保留的小数位数
* @param roundingMode 舍入模式比如四舍五入
* @return java.math.BigDecimal
* @date 2022/6/2 13:43
*/
public static BigDecimal divide(Double divisor,
Double dividend,
int scale,
RoundingMode roundingMode) {
if (divisor == null || dividend == null) {
throw new NullPointerException("传入的数据不能为空");
}
if (Double.compare(divisor, BigDecimal.ZERO.doubleValue()) == 0 ||
Double.compare(dividend, BigDecimal.ZERO.doubleValue()) == 0) {
return BigDecimal.ZERO;
}
return new BigDecimal(String.valueOf(divisor)).divide(new BigDecimal(String.valueOf(dividend)),
scale, roundingMode);
}
/**
* 除法
*
* @param divisor 除数
* @param dividend 被除数
* @param scale 保留的小数位数
* @param roundingMode 舍入模式比如四舍五入
* @return java.math.BigDecimal
* @date 2022/6/2 13:43
*/
public static BigDecimal divide(Double divisor,
Integer dividend,
int scale,
RoundingMode roundingMode) {
if (divisor == null || dividend == null) {
throw new NullPointerException("传入的数据不能为空");
}
if (Double.compare(divisor, BigDecimal.ZERO.doubleValue()) == 0 ||
Double.compare(dividend, BigDecimal.ZERO.doubleValue()) == 0) {
return BigDecimal.ZERO;
}
return new BigDecimal(String.valueOf(divisor)).divide(new BigDecimal(String.valueOf(dividend)),
scale, roundingMode);
}
/**
* 减法
*
* @param subtraction 减数
* @param minuend 被减数
* @return java.math.BigDecimal
* @date 2022/6/2 13:53
*/
public static BigDecimal subtract(BigDecimal subtraction,
BigDecimal minuend) {
if (subtraction == null || minuend == null) {
throw new NullPointerException("传入的数据不能为空");
}
return subtraction.subtract(minuend);
}
/**
* 减法
*
* @param subtraction 减数
* @param minuend 被减数
* @return java.math.BigDecimal
* @date 2022/6/2 13:53
*/
public static BigDecimal subtract(Double subtraction,
Double minuend) {
if (subtraction == null || minuend == null) {
throw new NullPointerException("传入的数据不能为空");
}
return new BigDecimal(String.valueOf(subtraction)).subtract(new BigDecimal(String.valueOf(minuend)));
}
/**
* 减法
*
* @param subtraction 减数
* @param minuend 被减数
* @return java.math.BigDecimal
* @date 2022/6/2 13:53
*/
public static BigDecimal subtract(BigDecimal subtraction,
Double minuend) {
if (subtraction == null || minuend == null) {
throw new NullPointerException("传入的数据不能为空");
}
return subtraction.subtract(new BigDecimal(minuend));
}
/**
* 加法
* @date 2022/6/7 17:31
* @param addend 加数
* @param summand 被加数
* @return java.lang.Double
*/
public static Double add(Double addend,
Double summand) {
if (addend == null || summand == null) {
throw new NullPointerException("传入的数据不能为空");
}
return new BigDecimal(addend.toString()).add(new BigDecimal(summand.toString())).doubleValue();
}
/**
* 加法
* @date 2022/6/7 17:31
* @param addend 加数
* @param summand 被加数
* @return java.lang.Double
*/
public static Double add(BigDecimal addend,
BigDecimal summand) {
if (addend == null || summand == null) {
throw new NullPointerException("传入的数据不能为空");
}
return addend.add(summand).doubleValue();
}
}

View File

@ -0,0 +1,82 @@
package com.ycwl.basic.utils;
import com.ycwl.basic.model.jwt.JwtInfo;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.JwtBuilder;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.Iterator;
import java.util.Map;
/**
* @author yangchen
*/
public class JwtAnalysisUtil {
/**
* 生成 Token
*
* @param jwtInfo
* @param priKey
* @param expireTime
* @return
* @throws Exception
*/
public static String generateToken(JwtInfo jwtInfo, byte[] priKey, LocalDateTime expireTime) throws Exception {
JwtBuilder builder = Jwts.builder().setSubject(jwtInfo.getAccount())
.claim("userId", jwtInfo.getUserId())
.claim("roleId", jwtInfo.getRoleId())
.claim("phone", jwtInfo.getPhone())
.claim("name", jwtInfo.getName())
// 返回从1970 000000 到现在的毫秒差实际的过期时间
.claim("expire", expireTime.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli());
return builder.signWith(SignatureAlgorithm.RS256, RsaKeyUtil.getPrivateKey(priKey)).compact();
}
/**
* 解析 Token
*
* @param token
* @param pubKey
* @return
* @throws Exception
*/
public static JwtInfo getInfoFromToken(String token, byte[] pubKey) throws Exception {
Claims body = (Claims) RsaKeyUtil.parserToken(token, pubKey).getBody();
Iterator var3 = body.entrySet().iterator();
while (var3.hasNext()) {
Map.Entry entry = (Map.Entry) var3.next();
if (!"sub".equals(entry.getKey())
&& !"userId".equals(entry.getKey())
&& !"phone".equals(entry.getKey())
&& !"roleId".equals(entry.getKey())
&& !"account".equals(entry.getKey())
&& !"name".equals(entry.getKey())
&& !"roleName".equals(entry.getKey())
&& !"expire".equals(entry.getKey()));
}
// convert
LocalDateTime expireTime = null;
try {
// expire time
Object expire = body.get("expire");
if (expire != null) {
expireTime = LocalDateTime.ofInstant(Instant.ofEpochMilli((Long) expire), ZoneId.systemDefault());
}
} catch (Exception e) {
e.printStackTrace();
}
return new JwtInfo(StringUtil.a(body.get("name")),
StringUtil.a(body.get("userId")),
StringUtil.a(body.get("roleId")),
body.getSubject(),
StringUtil.a(body.get("phone")),
expireTime);
}
}

View File

@ -0,0 +1,114 @@
package com.ycwl.basic.utils;
import com.ycwl.basic.exception.CheckTokenException;
import com.ycwl.basic.model.jwt.JwtInfo;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import java.time.LocalDateTime;
;
/**
* @author yangchen
*/
@SuppressWarnings("ALL")
@Slf4j
@Component
public class JwtTokenUtil {
@Getter
@Value("${jwt.expire:15}")
private int expire;
private static String PRI_KEY = "MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAKOpJ+Ob4VI6sipH47lNQF94YVjNvf/NS8x8gsq/qYG8JOM016prGpHBF6fZOv1yKDnBwJRwC+2oBm3PmybXUZiKIYScoLIFcoV9GbuZZ1ktEWpzUSbN4ZHMj2ylkVHi07HlR4L3PzJlbzC410yg2ZS2WKoanJRHUAmrcN4bvXvBAgMBAAECgYBw7LLdVh1uw5lTmy8CGM+mEEX7JFtJObpnajJE+2JWZh99tmRo7mXy1C0iX71YS4B9+baLtZRFc36cHneLoV5mqhWOf84W/zha+z5dlh1ErSLL6t8YKpJ2GQUMu9Y90VHf5eyhUTu0W7bc+Nvr3GSzaDpMy4fm0XjrazIBuYDvAQJBAOShdiZJnKPBLP98XsVD8L3EB1Tpe3qFviYHhvnhaafMmoY8AR3OqMAIn8jLUiUsIdiOpWL2tNFfCkk0kwLpb2kCQQC3QKXKQjY1j8YGrSQw8YFry5qFcdHP+ybw8lc090wHZjFYlpLSjL6AoTwt+bMyArr2WWCN9G/tU5aVLajZc/aZAkByMtAQGc664L+4MYgo4mG6d9Ltr930eh9bYYEjCVu76+/3QruQBuy1Vtlw81XpqVySjdXAU9hHiEBcBn20A6OZAkAW65IQ8ykel+X3zc4aBQrf9a5VBIBumAYt2tHHgSrUPhbr8qFYjlwBcKk7QuED302NJG6sMqeRMoRCElztHdD5AkAWZCbWQQtFmgWB9fZQxKT94c+zL7HJwgcmtmQq8JHgcoOE1jgi5bVksm8vhDeATOAUEAt0Dt+vwTPaPvFL5JdW";
private static String PUB_KEY = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCjqSfjm+FSOrIqR+O5TUBfeGFYzb3/zUvMfILKv6mBvCTjNNeqaxqRwRen2Tr9cig5wcCUcAvtqAZtz5sm11GYiiGEnKCyBXKFfRm7mWdZLRFqc1EmzeGRzI9spZFR4tOx5UeC9z8yZW8wuNdMoNmUtliqGpyUR1AJq3DeG717wQIDAQAB";
/**
* 生成 token
*
* @param jwtInfo
* @param otherInfo
* @param expireTime 会增加一个 expire 作为 token 的过期时间
* @return
* @throws Exception
*/
public String generateToken(JwtInfo jwtInfo) throws Exception {
// 过期时间默认 15
LocalDateTime expireTime = LocalDateTime.now().plusDays(expire);
byte[] bytes = RsaKeyUtil.toBytes(PRI_KEY);
String token = JwtAnalysisUtil.generateToken(jwtInfo, bytes, expireTime);
return token;
}
/**
* 解析Token
*
* @param token
* @return
* @throws Exception
*/
public JwtInfo parsingToken(String token) throws CheckTokenException {
try {
JwtInfo infoFromToken = JwtAnalysisUtil.getInfoFromToken(token, RsaKeyUtil.toBytes(PUB_KEY));
return infoFromToken;
} catch (Exception e) {
e.printStackTrace();
throw new CheckTokenException("token is invalid");
}
}
/*********************************************** 测试 ***************************************************/
/**
* 测试 token
*
* @param args
*/
// public static void main(String[] args) throws Exception {
//
// JwtInfo jwtInfo = new JwtInfo("阿豹", "1", "role1", "yangchen", 1, LocalDateTime.now(), new HashMap<>());
//
// long a = Instant.now().toEpochMilli();
//
// JwtTokenUtil jwtTokenUtil = new JwtTokenUtil();
// String token = jwtTokenUtil.generateToken(jwtInfo);
//
// log.info("==> generate token: " + (Instant.now().toEpochMilli() - a) + " ms");
//
// System.out.println("=======");
// System.out.println();
//
// System.out.println(token);
//
// System.out.println();
// System.out.println("=======");
//
// long b = Instant.now().toEpochMilli();
//
// JwtInfo jwtInfo1 = jwtTokenUtil.parsingToken(token);
//
// log.info("==> paring token end " + (Instant.now().toEpochMilli() - b) + " ms");
//
// System.out.println();
// System.out.println();
// System.out.println();
// System.out.println(jwtInfo);
// System.out.println("=======");
// System.out.println(jwtInfo1.toString());
//
// }
public static void main(String[] args) throws Exception {
JwtInfo jwtInfo = new JwtInfo();
jwtInfo.setUserId("1");
LocalDateTime expireTime = LocalDateTime.now().plusDays(9999999);
byte[] bytes = RsaKeyUtil.toBytes(PRI_KEY);
String token = JwtAnalysisUtil.generateToken(jwtInfo, bytes, expireTime);
System.out.println(token);
}
}

View File

@ -0,0 +1,180 @@
package com.ycwl.basic.utils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.BeanWrapper;
import org.springframework.beans.BeanWrapperImpl;
import java.beans.PropertyDescriptor;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
/**
* @date 2022年07月14日 14:12
* 数据格式转换工具类
*/
public class ObjectConvertUtils {
private static final Logger LOGGER = LoggerFactory.getLogger(ObjectConvertUtils.class);
/**
* 浅克隆
*
* @param source 原对象
* @param clazz 目标对象
* @return T
* @date 2022/4/6 13:45
*/
public static <T> T clone(Object source, Class<T> clazz) {
return clone(source, clazz, true);
}
/**
*
* @date 2022/7/18 16:36
* @param source 原对象
* @param clazz 目标对象
* @param whetherAssignNull 是否赋值空值:true是 false否
* @return T
*/
public static <T> T clone(Object source, Class<T> clazz, Boolean whetherAssignNull) {
T target;
if (source == null) {
return null;
}
try {
target = clazz.newInstance();
if (whetherAssignNull) {
BeanUtils.copyProperties(source, target);
} else {
BeanUtils.copyProperties(source, target, getNullPropertyNames(source));
}
return target;
} catch (Exception e) {
LOGGER.error("数据转换异常", e);
return null;
}
}
/**
* 对象与对象之间的数据转换
*
* @param source 转换的数据对象
* @param target 需要转换数据的对象
* @date 2022/7/14 17:24
*/
public static void clone(Object source, Object target) {
clone(source, target, true);
}
/**
*
* @date 2022/7/18 16:39
* @param source 转换的数据对象
* @param target 需要转换数据的对象
* @param whetherAssignNull 是否赋值空值:true是 false否
*/
public static void clone(Object source, Object target, Boolean whetherAssignNull) {
if (source == null) {
return;
}
try {
if (whetherAssignNull) {
BeanUtils.copyProperties(source, target, getNullPropertyNames(source));
} else {
BeanUtils.copyProperties(source, target);
}
} catch (Exception e) {
LOGGER.error("数据转换异常", e);
}
}
/**
* 对象与对象之间的数据转换
*
* @param source 转换的数据对象
* @param target 需要转换数据的对象
* @date 2022/7/15 9:11
*/
public static void cglibBeanCopierCloneObject(Object source, Object target) {
BeanCopierUtils.copyProperties(source, target);
}
/**
* 对象与对象之间的数据转换
*
* @param source 转换的数据对象
* @param target 需要转换数据的对象
* @date 2022/7/15 9:11
*/
public static <T> T cglibBeanCopierCloneObject(Object source, Class<T> target) {
T t;
try {
t = target.newInstance();
BeanCopierUtils.copyProperties(source, t);
} catch (InstantiationException | IllegalAccessException e) {
throw new RuntimeException(e);
}
return t;
}
/**
* 将list集合转换为传入的对象的数据集合
*
* @param sourceList 原数据集合
* @param clazz 需要转换的集合数据对象
* @return java.util.List<T>
* @date 2022/4/6 13:49
*/
public static <T> List<T> cloneList(List<?> sourceList, Class<T> clazz) {
return cloneList(sourceList, clazz, true);
}
/**
*
* @date 2022/7/18 16:41
* @param sourceList 原数据集合
* @param clazz 需要转换的集合数据对象
* @param whetherAssignNull 是否赋值空值:true是 false否
* @return java.util.List<T>
*/
public static <T> List<T> cloneList(List<?> sourceList, Class<T> clazz, Boolean whetherAssignNull) {
try {
List<T> targetList = new ArrayList<>(sourceList.size());
for (Object source : sourceList) {
if (whetherAssignNull) {
targetList.add(clone(source, clazz));
} else {
targetList.add(clone(source, clazz, false));
}
}
return targetList;
} catch (Exception e) {
LOGGER.error("数据转换异常", e);
return null;
}
}
/**
* 获取需要忽略的属性
*/
public static String[] getNullPropertyNames(Object source) {
final BeanWrapper src = new BeanWrapperImpl(source);
PropertyDescriptor[] pds = src.getPropertyDescriptors();
Set<String> emptyNames = new HashSet<>();
for (PropertyDescriptor pd : pds) {
Object srcValue = src.getPropertyValue(pd.getName());
// 此处判断可根据需求修改
if (srcValue == null) {
emptyNames.add(pd.getName());
}
}
String[] result = new String[emptyNames.size()];
return emptyNames.toArray(result);
}
}

View File

@ -0,0 +1,77 @@
package com.ycwl.basic.utils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.*;
import org.springframework.stereotype.Component;
import java.util.List;
/**
* @date 2022年08月08日 16:06
* redis缓存操作行为工具类
*/
@Component
public class RedisCacheOperationUtils {
/**
* string类型的redis操作类
*/
private static StringRedisTemplate stringRedisTemplate;
/**
* 通用的redis操作类
*/
private static RedisTemplate redisTemplate;
/**
* 创建string类型的操作对象
*/
public static BoundValueOperations<String, String> createValueOperations(String cacheKey) {
return stringRedisTemplate.boundValueOps(cacheKey);
}
/**
* 创建list类型的操作对象
*/
public static BoundListOperations<String, List<String>> createListOperations(String cacheKey) {
return redisTemplate.boundListOps(cacheKey);
}
/**
* 创建hash类型的操作对象
*/
public static BoundHashOperations createHashOperations(String cacheKey) {
return redisTemplate.boundHashOps(cacheKey);
}
/**
* 创建set类型的操作对象
*/
public static BoundSetOperations createSetOperations(String cacheKey) {
return redisTemplate.boundSetOps(cacheKey);
}
/**
* 创建zset类型的操作对象
*/
public static BoundZSetOperations createZSetOperations(String cacheKey) {
return redisTemplate.boundZSetOps(cacheKey);
}
/**
* 判断缓存key值是否存在
*/
public static Boolean hasKey(String cacheKey) {
return redisTemplate.hasKey(cacheKey);
}
/**
* 删除缓存的redis缓存key
*/
public static Boolean delete(String cacheKey) {
return redisTemplate.delete(cacheKey);
}
@Autowired
public void setStringRedisTemplate(StringRedisTemplate stringRedisTemplate) {
RedisCacheOperationUtils.stringRedisTemplate = stringRedisTemplate;
}
@Autowired
public void setRedisTemplate(RedisTemplate redisTemplate) {
RedisCacheOperationUtils.redisTemplate = redisTemplate;
}
}

View File

@ -0,0 +1,79 @@
package com.ycwl.basic.utils;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jws;
import io.jsonwebtoken.Jwts;
import java.io.IOException;
import java.security.*;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;
/**
* @author yangchen
*/
@SuppressWarnings("ALL")
public class RsaKeyUtil {
public RsaKeyUtil() {
}
public static PublicKey getPublicKey(byte[] publicKey) throws Exception {
X509EncodedKeySpec spec = new X509EncodedKeySpec(publicKey);
return KeyFactory.getInstance("RSA").generatePublic(spec);
}
public static PrivateKey getPrivateKey(byte[] privateKey) throws Exception {
PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(privateKey);
return KeyFactory.getInstance("RSA").generatePrivate(spec);
}
public static Map<String, byte[]> generateKey(String password) throws IOException, NoSuchAlgorithmException {
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
SecureRandom secureRandom = new SecureRandom(password.getBytes());
keyPairGenerator.initialize(1024, secureRandom);
KeyPair keyPair;
byte[] publicKeyBytes = (keyPair = keyPairGenerator.genKeyPair()).getPublic().getEncoded();
byte[] privateKeyBytes = keyPair.getPrivate().getEncoded();
HashMap map;
(map = new HashMap()).put("pub", publicKeyBytes);
map.put("pri", privateKeyBytes);
return map;
}
public static String toHexString(byte[] b) {
return Base64.getEncoder().encodeToString(b);
}
public static final byte[] toBytes(String s) throws IOException {
return Base64.getDecoder().decode(s);
}
public static Jws<Claims> parserToken(String token, byte[] pubKey) throws Exception {
return Jwts.parser().setSigningKey(RsaKeyUtil.getPublicKey(pubKey)).parseClaimsJws(token);
}
/**
* 测试类
*
* @param args
* @throws NoSuchAlgorithmException
*/
public static void main(String[] args) throws Exception {
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
SecureRandom secureRandom = new SecureRandom("123".getBytes());
keyPairGenerator.initialize(1024, secureRandom);
KeyPair keyPair = keyPairGenerator.genKeyPair();
System.out.println(keyPair.getPublic().getEncoded());
System.out.println("====");
/**
* 生成公私密钥
*/
Map<String, byte[]> keyMap = RsaKeyUtil.generateKey("123456");
}
}

View File

@ -0,0 +1,138 @@
package com.ycwl.basic.utils;
import com.ycwl.basic.model.snowFlake.UniqueId;
import com.ycwl.basic.model.snowFlake.UniqueIdMetaData;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import java.util.Date;
/**
* @author Created by liuhongguang
* @Description
*/
@Component
public class SnowFlakeUtil {
private Logger log = LoggerFactory.getLogger(com.ycwl.basic.utils.SnowFlakeUtil.class);
/**
* 记录上一毫秒数
*/
private static long lastTimestamp = -1L;
/**
* 记录毫秒内的序列0-4095
*/
private static long sequence = 0L;
private static Long machineId = 1L;
private static Long datacenterId =1L;
public static synchronized String getId() {
long timestamp = System.currentTimeMillis();
// 如果当前时间小于上一次ID生成的时间戳说明系统时钟被修改过回退在上一次ID生成时间之前应当抛出异常
if (timestamp < lastTimestamp) {
throw new IllegalStateException(
String.format("Clock moved backwards. Refusing to generate id for %d milliseconds", lastTimestamp - timestamp));
}
//如果是同一时间生成的则进行毫秒内序列
if (lastTimestamp == timestamp) {
sequence = (sequence + 1) & UniqueIdMetaData.SEQUENCE_MASK;
//毫秒内序列溢出
if (sequence == 0) {
//阻塞到下一个毫秒,获得新的时间戳
timestamp = System.currentTimeMillis();
while (timestamp <= lastTimestamp) {
timestamp = System.currentTimeMillis();
}
return String.valueOf(timestamp);
}
}
//时间戳改变毫秒内序列重置
else {
sequence = 0L;
}
// 上次生成ID的时间截
lastTimestamp = timestamp;
// 移位并通过或运算组成64位ID
return String.valueOf(((timestamp - UniqueIdMetaData.START_TIME) << UniqueIdMetaData.TIMESTAMP_LEFT_SHIFT_BITS)
| (datacenterId << UniqueIdMetaData.DATACENTER_SHIFT_BITS)
| (machineId<< UniqueIdMetaData.MACHINE_SHIFT_BITS)
| sequence);
}
public UniqueId explainId(long id) {
UniqueId uniqueId = com.ycwl.basic.utils.SnowFlakeUtil.convert(id);
if (uniqueId == null) {
log.error("==> 解析ID失败, ID不合法");
return null;
}
return uniqueId;
}
public Date transTime(long time) {
return new Date(time + UniqueIdMetaData.START_TIME);
}
/**
* 唯一ID对象解析返回ID
*
* @param uniqueId
* @return
*/
public static long convert(UniqueId uniqueId) {
long result = 0;
try {
result = 0L;
result |= uniqueId.getSequence();
result |= uniqueId.getMachineId() << UniqueIdMetaData.MACHINE_SHIFT_BITS;
result |= uniqueId.getDatacenterId() << UniqueIdMetaData.DATACENTER_SHIFT_BITS;
result |= uniqueId.getTimestamp() << UniqueIdMetaData.TIMESTAMP_LEFT_SHIFT_BITS;
} catch (Exception e) {
e.printStackTrace();
return result;
}
return result;
}
public static UniqueId convert(long id) {
UniqueId uniqueId = null;
try {
uniqueId = new UniqueId();
uniqueId.setSequence(id & UniqueIdMetaData.SEQUENCE_MASK);
uniqueId.setMachineId((id >>> UniqueIdMetaData.MACHINE_SHIFT_BITS) & UniqueIdMetaData.MACHINE_MASK);
uniqueId.setDatacenterId((id >>> UniqueIdMetaData.DATACENTER_SHIFT_BITS) & UniqueIdMetaData.DATACENTER_MASK);
uniqueId.setTimestamp((id >>> UniqueIdMetaData.TIMESTAMP_LEFT_SHIFT_BITS) & UniqueIdMetaData.TIMESTAMP_MASK);
} catch (Exception e) {
e.printStackTrace();
return uniqueId;
}
return uniqueId;
}
}

View File

@ -0,0 +1,11 @@
package com.ycwl.basic.utils;
public final class StringUtil {
public StringUtil() {
}
public static String a(Object obj) {
return obj == null ? "" : obj.toString();
}
}

View File

@ -0,0 +1,200 @@
package com.ycwl.basic.xss;
import cn.hutool.core.collection.CollectionUtil;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.text.StringEscapeUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.Map;
/**
* 重新包装一下Request重写一些获取参数的方法将每个参数都进行过滤
*/
public class XSSHttpServletRequestWrapper extends HttpServletRequestWrapper {
private static final Logger logger = LoggerFactory.getLogger(XSSHttpServletRequestWrapper.class);
private HttpServletRequest request;
/**
* 请求体 RequestBody
*/
private String reqBody;
/**
* Constructs a request object wrapping the given request.
*
* @param request The request to wrap
* @throws IllegalArgumentException if the request is null
*/
public XSSHttpServletRequestWrapper(HttpServletRequest request) {
super(request);
logger.info("---xss XSSHttpServletRequestWrapper created-----");
this.request = request;
reqBody = getBodyString();
}
@Override
public String getQueryString() {
return StringEscapeUtils.escapeHtml4(super.getQueryString());
}
/**
* The default behavior of this method is to return getParameter(String
* name) on the wrapped request object.
*
* @param name
*/
@Override
public String getParameter(String name) {
logger.info("---xss XSSHttpServletRequestWrapper work getParameter-----");
String parameter = request.getParameter(name);
if (StringUtils.isNotBlank(parameter)) {
logger.info("----filter before--name:{}--value:{}----", name, parameter);
parameter = StringEscapeUtils.escapeHtml4(parameter);
logger.info("----filter after--name:{}--value:{}----", name, parameter);
}
return parameter;
}
/**
* The default behavior of this method is to return
* getParameterValues(String name) on the wrapped request object.
*
* @param name
*/
@Override
public String[] getParameterValues(String name) {
logger.info("---xss XSSHttpServletRequestWrapper work getParameterValues-----");
String[] parameterValues = request.getParameterValues(name);
if (parameterValues != null && parameterValues.length > 0) {
if (!CollectionUtil.isEmpty(Arrays.asList(parameterValues))) {
// @Belief_7 指正 这种方式不能更改parameterValues里面的值要换成下面👇的写法
//for (String value : parameterValues) {
// logger.info("----filter before--name:{}--value:{}----", name, value);
// value = StringEscapeUtils.escapeHtml4(value);
// logger.info("----filter after--name:{}--value:{}----", name, value);
// }
for (int i = 0; i < parameterValues.length; i++)
{
parameterValues[i] = StringEscapeUtils.escapeHtml4(parameterValues[i]);
}
}
}
return parameterValues;
}
/**
* The default behavior of this method is to return getParameterMap() on the
* wrapped request object.
*/
@Override
public Map<String, String[]> getParameterMap() {
logger.info("---xss XSSHttpServletRequestWrapper work getParameterMap-----");
Map<String, String[]> map = request.getParameterMap();
if (map != null && !map.isEmpty()) {
for (String[] value : map.values()) {
/*循环所有的value*/
for (String str : value) {
logger.info("----filter before--value:{}----", str, str);
str = StringEscapeUtils.escapeHtml4(str);
logger.info("----filter after--value:{}----", str, str);
}
}
}
return map;
}
/*重写输入流的方法因为使用RequestBody的情况下是不会走上面的方法的*/
/**
* The default behavior of this method is to return getReader() on the
* wrapped request object.
*/
@Override
public BufferedReader getReader() throws IOException {
logger.info("---xss XSSHttpServletRequestWrapper work getReader-----");
return new BufferedReader(new InputStreamReader(getInputStream()));
}
/**
* The default behavior of this method is to return getInputStream() on the
* wrapped request object.
*/
@Override
public ServletInputStream getInputStream() throws IOException {
logger.info("---xss XSSHttpServletRequestWrapper work getInputStream-----");
/*创建字节数组输入流*/
final ByteArrayInputStream bais = new ByteArrayInputStream(reqBody.getBytes(StandardCharsets.UTF_8));
return new ServletInputStream() {
@Override
public boolean isFinished() {
return false;
}
@Override
public boolean isReady() {
return false;
}
@Override
public void setReadListener(ReadListener listener) {
}
@Override
public int read() throws IOException {
return bais.read();
}
};
}
/**
* 获取请求体
*
* @return 请求体
*/
private String getBodyString() {
StringBuilder builder = new StringBuilder();
InputStream inputStream = null;
BufferedReader reader = null;
try {
inputStream = request.getInputStream();
reader = new BufferedReader(new InputStreamReader(inputStream));
String line;
while ((line = reader.readLine()) != null) {
builder.append(line);
}
} catch (IOException e) {
logger.error("-----get Body String Error:{}----", e.getMessage(), e);
} finally {
if (inputStream != null) {
try {
inputStream.close();
} catch (IOException e) {
logger.error("-----get Body String Error:{}----", e.getMessage(), e);
}
}
if (reader != null) {
try {
reader.close();
} catch (IOException e) {
logger.error("-----get Body String Error:{}----", e.getMessage(), e);
}
}
}
return builder.toString();
}
}

View File

@ -0,0 +1,17 @@
package com.ycwl.basic.xss;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import org.apache.commons.text.StringEscapeUtils;
import java.io.IOException;
public class XssJacksonDeserializer extends JsonDeserializer<String> {
@Override
public String deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException {
return StringEscapeUtils.escapeHtml4(jp.getText());
}
}

View File

@ -0,0 +1,18 @@
package com.ycwl.basic.xss;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import org.apache.commons.text.StringEscapeUtils;
import java.io.IOException;
public class XssJacksonSerializer extends JsonSerializer<String>{
@Override
public void serialize(String value, JsonGenerator jgen, SerializerProvider provider) throws IOException {
jgen.writeString(StringEscapeUtils.escapeHtml4(value));
}
}

View File

@ -0,0 +1,62 @@
server:
port: 8030
spring:
application:
name: basic
main:
allow-bean-definition-overriding: true
mvc:
# 启用hiddenMethod过滤器(头像上传)
hiddenmethod:
filter:
enabled: true
datasource: # 数据源的相关配置
type: com.zaxxer.hikari.HikariDataSource # 数据源类型HikariCP
driver-class-name: com.mysql.cj.jdbc.Driver # mysql驱动
url: jdbc:mysql://8.134.112.96:3306/liuying_mgmt_re?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true
username: root
password: yckj2017
hikari:
connection-timeout: 30000 # 等待连接池分配连接的最大时长毫秒超过这个时长还没可用的连接则发生SQLException 默认:30秒
minimum-idle: 5 # 最小连接数
maximum-pool-size: 20 # 最大连接数
auto-commit: true # 事务自动提交
idle-timeout: 60000 # 连接超时的最大时长(毫秒)
pool-name: DateSourceHikariCP # 连接池名字
max-lifetime: 180000 # 连接的生命时长(毫秒)
connection-test-query: SELECT 1 # 连接测试语句
jackson:
date-format: "yyyy-MM-dd HH:mm:ss"
time-zone: GMT+8
redis:
host: 10.59.3.242
port: 6379
# 密码过于复杂需要使用''引起来,要不可能导致项目无法启动,因为无法识别特殊字符
password: yckj2018
jedis:
pool:
max-active: -1 # 连接池最大连接数(使用负值表示没有限制)
min-idle: 1 # 连接池中的最小空闲连接
time-between-eviction-runs: 3000
timeout: 40000
# 配置用户头像存放静态资源文件夹
resources:
static-locations: classpath:/META-INF/resources/,classpath:/resources/,classpath:/static/,classpath:/public/
# 配置请求文件大小
servlet:
multipart:
max-file-size: 10MB
max-request-size: 10MB
# MyBatis
mybatis-plus:
configuration:
# 开启驼峰命名法
map-underscore-to-camel-case: true
use-generated-keys: true
# 这个配置会将执行的sql打印出来在开发或测试的时候可以用
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
# 指定使用的日志配置文件
logging:
config: classpath:logback-spring.xml

View File

@ -0,0 +1,133 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration debug="true">
<!-- appender是configuration的子节点是负责写日志的组件。 -->
<!-- ConsoleAppender把日志输出到控制台 -->
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<!-- 默认情况下,每个日志事件都会立即刷新到基础输出流。 这种默认方法更安全因为如果应用程序在没有正确关闭appender的情况下退出则日志事件不会丢失。
但是为了显着增加日志记录吞吐量您可能希望将immediateFlush属性设置为false -->
<!--<immediateFlush>true</immediateFlush>-->
<encoder>
<!-- %37():如果字符没有37个字符长度,则左侧用空格补齐 -->
<!-- %-37():如果字符没有37个字符长度,则右侧用空格补齐 -->
<!-- %15.15():如果记录的线程字符长度小于15(第一个)则用空格在左侧补齐,如果字符长度大于15(第二个),则从开头开始截断多余的字符 -->
<!-- %-40.40():如果记录的logger字符长度小于40(第一个)则用空格在右侧补齐,如果字符长度大于40(第二个),则从开头开始截断多余的字符 -->
<!-- %msg日志打印详情 -->
<!-- %n:换行符 -->
<!-- %highlight():转换说明符以粗体红色显示其级别为ERROR的事件红色为WARNBLUE为INFO以及其他级别的默认颜色。 -->
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %highlight(%-5level) --- [%15.15(%thread)] %cyan(%-40.40(%logger{40})) : %msg%n</pattern>
<!-- 控制台也要使用UTF-8不要使用GBK否则会中文乱码 -->
<charset>UTF-8</charset>
</encoder>
</appender>
<!-- info 日志-->
<!-- RollingFileAppender滚动记录文件先将日志记录到指定文件当符合某个条件时将日志记录到其他文件 -->
<!-- 以下的大概意思是1.先按日期存日志日期变了将前一天的日志文件名重命名为XXX%日期%索引新的日志仍然是project_info.log -->
<!-- 2.如果日期没有发生变化但是当前日志的文件大小超过10MB时对当前日志进行分割 重命名-->
<appender name="info_log" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!--日志文件路径和名称-->
<File>logs/project_info.log</File>
<!--是否追加到文件末尾,默认为true-->
<append>true</append>
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>ERROR</level>
<onMatch>DENY</onMatch><!-- 如果命中ERROR就禁止这条日志 -->
<onMismatch>ACCEPT</onMismatch><!-- 如果没有命中就使用这条规则 -->
</filter>
<!--有两个与RollingFileAppender交互的重要子组件。 第一个RollingFileAppender子组件即RollingPolicy:负责执行翻转所需的操作。
RollingFileAppender的第二个子组件即TriggeringPolicy:将确定是否以及何时发生翻转。 因此RollingPolicy负责什么和TriggeringPolicy负责什么时候.
作为任何用途RollingFileAppender必须同时设置RollingPolicy和TriggeringPolicy,但是如果其RollingPolicy也实现了TriggeringPolicy接口则只需要显式指定前者。-->
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<!-- 日志文件的名字会根据fileNamePattern的值每隔一段时间改变一次 -->
<!-- 文件名logs/project_info.2017-12-05.0.log -->
<!-- 注意SizeAndTimeBasedRollingPolicy中 i和d令牌都是强制性的必须存在要不会报错 -->
<fileNamePattern>logs/project_info.%d.%i.log</fileNamePattern>
<!-- 每产生一个日志文件该日志文件的保存期限为30天, ps:maxHistory的单位是根据fileNamePattern中的翻转策略自动推算出来的,例如上面选用了yyyy-MM-dd,则单位为天
如果上面选用了yyyy-MM,则单位为月,另外上面的单位默认为yyyy-MM-dd-->
<maxHistory>30</maxHistory>
<!-- 每个日志文件到10mb的时候开始切分最多保留30天但最大到20GB哪怕没到30天也要删除多余的日志 -->
<totalSizeCap>20GB</totalSizeCap>
<!-- maxFileSize:这是活动文件的大小默认值是10MB测试时可改成5KB看效果 -->
<maxFileSize>10MB</maxFileSize>
</rollingPolicy>
<!--编码器-->
<encoder>
<!-- pattern节点用来设置日志的输入格式 ps:日志文件中没有设置颜色,否则颜色部分会有ESC[0:39em等乱码-->
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %-5level --- [%15.15(%thread)] %-40.40(%logger{40}) : %msg%n</pattern>
<!-- 记录日志的编码:此处设置字符集 - -->
<charset>UTF-8</charset>
</encoder>
</appender>
<!-- error 日志-->
<!-- RollingFileAppender滚动记录文件先将日志记录到指定文件当符合某个条件时将日志记录到其他文件 -->
<!-- 以下的大概意思是1.先按日期存日志日期变了将前一天的日志文件名重命名为XXX%日期%索引新的日志仍然是project_error.log -->
<!-- 2.如果日期没有发生变化但是当前日志的文件大小超过10MB时对当前日志进行分割 重命名-->
<appender name="error_log" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!--日志文件路径和名称-->
<File>logs/project_error.log</File>
<!--是否追加到文件末尾,默认为true-->
<append>true</append>
<!-- ThresholdFilter过滤低于指定阈值的事件。 对于等于或高于阈值的事件ThresholdFilter将在调用其decision方法时响应NEUTRAL。 但是,将拒绝级别低于阈值的事件 -->
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>ERROR</level><!-- 低于ERROR级别的日志debug,info将被拒绝等于或者高于ERROR的级别将相应NEUTRAL -->
</filter>
<!--有两个与RollingFileAppender交互的重要子组件。 第一个RollingFileAppender子组件即RollingPolicy:负责执行翻转所需的操作。
RollingFileAppender的第二个子组件即TriggeringPolicy:将确定是否以及何时发生翻转。 因此RollingPolicy负责什么和TriggeringPolicy负责什么时候.
作为任何用途RollingFileAppender必须同时设置RollingPolicy和TriggeringPolicy,但是如果其RollingPolicy也实现了TriggeringPolicy接口则只需要显式指定前者。-->
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<!-- 活动文件的名字会根据fileNamePattern的值每隔一段时间改变一次 -->
<!-- 文件名logs/project_error.2017-12-05.0.log -->
<!-- 注意SizeAndTimeBasedRollingPolicy中 i和d令牌都是强制性的必须存在要不会报错 -->
<fileNamePattern>logs/project_error.%d.%i.log</fileNamePattern>
<!-- 每产生一个日志文件该日志文件的保存期限为30天, ps:maxHistory的单位是根据fileNamePattern中的翻转策略自动推算出来的,例如上面选用了yyyy-MM-dd,则单位为天
如果上面选用了yyyy-MM,则单位为月,另外上面的单位默认为yyyy-MM-dd-->
<maxHistory>30</maxHistory>
<!-- 每个日志文件到10mb的时候开始切分最多保留30天但最大到20GB哪怕没到30天也要删除多余的日志 -->
<totalSizeCap>20GB</totalSizeCap>
<!-- maxFileSize:这是活动文件的大小默认值是10MB测试时可改成5KB看效果 -->
<maxFileSize>10MB</maxFileSize>
</rollingPolicy>
<!--编码器-->
<encoder>
<!-- pattern节点用来设置日志的输入格式 ps:日志文件中没有设置颜色,否则颜色部分会有ESC[0:39em等乱码-->
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %-5level --- [%15.15(%thread)] %-40.40(%logger{40}) : %msg%n</pattern>
<!-- 记录日志的编码:此处设置字符集 - -->
<charset>UTF-8</charset>
</encoder>
</appender>
<!--给定记录器的每个启用的日志记录请求都将转发到该记录器中的所有appender以及层次结构中较高的appender不用在意level值
换句话说appender是从记录器层次结构中附加地继承的。
例如如果将控制台appender添加到根记录器则所有启用的日志记录请求将至少在控制台上打印。
如果另外将文件追加器添加到记录器例如L则对L和L'子项启用的记录请求将打印在文件和控制台上。
通过将记录器的additivity标志设置为false可以覆盖此默认行为以便不再添加appender累积-->
<!-- configuration中最多允许一个root别的logger如果没有设置级别则从父级别root继承 -->
<root level="INFO">
<appender-ref ref="STDOUT" />
</root>
<!-- 指定项目中某个包,当有日志操作行为时的日志记录级别 -->
<!-- 级别依次为【从高到低】FATAL > ERROR > WARN > INFO > DEBUG > TRACE -->
<logger name="com.ycwl.basic" level="INFO">
<appender-ref ref="info_log" />
<appender-ref ref="error_log" />
</logger>
<!-- 利用logback输入mybatis的sql日志
注意:如果不加 additivity="false" 则此logger会将输出转发到自身以及祖先的logger中就会出现日志文件中sql重复打印-->
<logger name="com.ycwl.basic.mapper" level="DEBUG" additivity="false">
<appender-ref ref="info_log" />
<appender-ref ref="error_log" />
<appender-ref ref="STDOUT" />
</logger>
<!-- additivity=false代表禁止默认累计的行为即com.atomikos中的日志只会记录到日志文件中不会输出层次级别更高的任何appender-->
<logger name="com.ycwl.basic" level="INFO" additivity="false">
<appender-ref ref="info_log" />
<appender-ref ref="error_log" />
<appender-ref ref="STDOUT" />
</logger>
</configuration>

View File

@ -0,0 +1,103 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.ycwl.basic.mapper.pc.AdminUserMapper">
<insert id="add" parameterType="com.ycwl.basic.model.pc.adminUser.req.AddOrUpdateAdminUserReqVO">
insert into admin_user(`id`,
`role_id`,
`staff_id`,
`account`,
`password`)
values (#{id},
#{roleId},
#{staffId},
#{account},
#{password})
</insert>
<update id="delete">
update
admin_user
set is_remove=1
where id = #{id}
</update>
<update id="resetPassword" parameterType="com.ycwl.basic.model.pc.adminUser.req.ResetPasswordReqVO">
update
admin_user
set password=#{password}
where id = #{id}
</update>
<update id="update" parameterType="com.ycwl.basic.model.pc.adminUser.req.AddOrUpdateAdminUserReqVO">
update admin_user
set `role_id` =#{roleId},
`staff_id` =#{staffId}
where id = #{id}
</update>
<update id="updatePassword">
update
admin_user
set password=#{newPwd}
where staff_id = #{id}
and is_remove = 0
</update>
<select id="list" parameterType="com.ycwl.basic.model.pc.adminUser.req.AdminUserListReqVO"
resultType="com.ycwl.basic.model.pc.adminUser.resp.AdminUserListRespVO">
select
s.id as staffId,
au.id,
s.phone,
s.name as staffName,
s.job_no,
c.name as companyName,
s.company_id,
r.id as roleId,
r.name as roleName
from admin_user au,
staff s,
company c,
role r
where au.staff_id = s.id
and au.is_remove=0
and au.role_id = r.id
and s.company_id = c.id
and s.is_remove=0
<if test="name!=null and name!=''">
and
locate(#{name},s.`name`) > 0
</if>
<if test="phone!=null and phone!=''">
and
locate(#{phone},s.`phone`) > 0
</if>
<if test="jobNo!=null and jobNo!=''">
and
locate(#{jobNo},s.`job_no`) > 0
</if>
<if test="roleId!=null and roleId!=''">
and
r.id=#{roleId}
</if>
<if test="companyId!=null and companyId!=''">
and
s.company_id=#{companyId}
</if>
</select>
<select id="login" resultType="com.ycwl.basic.model.pc.adminUser.entity.LoginEntity">
select
au.account,
au.password,
au.role_id
from admin_user au
where account = #{account}
and au.is_remove = 0
</select>
<select id="getPasswordByAccount" resultType="java.lang.String">
select `password`
from admin_user
where staff_id = #{id}
and is_remove = 0
</select>
</mapper>

View File

@ -0,0 +1,31 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.ycwl.basic.mapper.pc.MenuMapper">
<insert id="addRoleMenu">
insert into role_menu(`role_id`, `menu_id`)
values
<foreach collection="list" item="item" separator=",">
(#{id},#{item})
</foreach>
</insert>
<delete id="delete">
delete
from role_menu
where role_id = #{id}
</delete>
<select id="getListByType" resultType="com.ycwl.basic.model.pc.menu.MenuNode">
select id,
parent_id,
target,
`name`,
`type`,
sort
from menu
where is_remove = 0
and business_type = #{type}
</select>
</mapper>

View File

@ -0,0 +1,80 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.ycwl.basic.mapper.pc.RoleMapper">
<insert id="add" parameterType="com.ycwl.basic.model.pc.role.req.AddOrUpdateRoleReqVO">
insert into role(`id`, `name`, `type`)
values (#{id}, #{name}, #{type})
</insert>
<update id="delete">
update
role
set is_remove=1
where id = #{id}
</update>
<update id="update" parameterType="com.ycwl.basic.model.pc.role.req.AddOrUpdateRoleReqVO">
update
role
set `name`=#{name}
where id = #{id}
</update>
<select id="list" resultType="com.ycwl.basic.model.pc.role.resp.RoleListRespVO">
select
`id`,
`name`,
`status`,
create_time
from
role
where
is_remove=0
and
`type`=#{type}
<if test="name!=null and name!=''">
and
locate(#{name},`name`) > 0
</if>
</select>
<select id="getMenuById" resultType="com.ycwl.basic.model.pc.menu.MenuNode">
select m.`id`,
m.`parent_id`,
m.`target`,
m.`name`,
m.`type`,
m.`sort`
from menu m,
role_menu rm
where is_remove = 0
and business_type = 0
and rm.menu_id = m.id
and rm.role_id = #{id}
</select>
<select id="getRoleStatus" resultType="java.lang.Integer">
select
`status`
from
role
where
id = #{id}
</select>
<update id="updateStatus">
update
role
set status =
(CASE
status
WHEN 1 THEN
0
WHEN 0 THEN
1
ELSE null
END)
where id = #{id}
</update>
</mapper>

View File

@ -0,0 +1,13 @@
package com.ycwl.basic;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
class BasicApplicationTests {
@Test
void contextLoads() {
}
}