feat(修改): 🚀 不推送logs文件

This commit is contained in:
bunny 2024-05-16 08:36:41 +08:00
parent d621865528
commit 17ddb8750e
72 changed files with 2287 additions and 2 deletions

3
.gitignore vendored
View File

@ -18,6 +18,8 @@ target/
*.iws *.iws
*.iml *.iml
*.ipr *.ipr
logs
logs/**
### NetBeans ### ### NetBeans ###
/nbproject/private/ /nbproject/private/
@ -31,4 +33,3 @@ build/
### VS Code ### ### VS Code ###
.vscode/ .vscode/
logs

View File

@ -0,0 +1,75 @@
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>cn.bunny</groupId>
<artifactId>common</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<artifactId>common-generator</artifactId>
<packaging>jar</packaging>
<name>common-utils</name>
<url>https://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.14</version>
</dependency>
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>2.1</version>
</dependency>
<!--mysql-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<!-- mysql连接池 -->
<dependency>
<groupId>com.zaxxer</groupId>
<artifactId>HikariCP</artifactId>
<version>5.1.0</version>
</dependency>
<!-- mybatis-plus -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-spring-boot3-starter</artifactId>
</dependency>
<!-- 数据库代码生成器 - 新版 -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-generator</artifactId>
<version>3.5.6</version>
</dependency>
<dependency>
<groupId>org.apache.velocity</groupId>
<artifactId>velocity-engine-core</artifactId>
<version>2.3</version>
</dependency>
<!-- 数据库代码生成器 - 旧版 -->
<!-- <dependency> -->
<!-- <groupId>com.baomidou</groupId> -->
<!-- <artifactId>mybatis-plus-generator</artifactId> -->
<!-- <version>3.4.1</version> -->
<!-- </dependency> -->
<!-- <dependency> -->
<!-- <groupId>org.apache.velocity</groupId> -->
<!-- <artifactId>velocity-engine-core</artifactId> -->
<!-- <version>2.0</version> -->
<!-- </dependency> -->
<!-- spring-web -->
</dependencies>
</project>

View File

@ -0,0 +1,84 @@
package cn.bunny.common.generator;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.generator.FastAutoGenerator;
import com.baomidou.mybatisplus.generator.config.OutputFile;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
import org.apache.ibatis.annotations.Mapper;
import java.util.Collections;
public class NewCodeGet {
// 数据连接
public static final String sqlHost = "jdbc:mysql://106.15.251.123:3305/bunny_docs?serverTimezone=GMT%2B8&useSSL=false&characterEncoding=utf-8&allowPublicKeyRetrieval=true";
// 作者名称
public static final String author = "Bunny";
// 公共路径
public static final String outputDir = "F:\\web项目\\PC\\BunnyNote\\bunny-server\\service\\service-admin";
// 实体类名称
public static final String entity = "Bunny";
public static void main(String[] args) {
Generation("email_users");
}
/**
* 根据表名生成相应结构代码
*
* @param tableName 表名
*/
public static void Generation(String... tableName) {
// TODO 修改数据库路径账户密码
FastAutoGenerator.create(sqlHost, "root", "02120212")
.globalConfig(builder -> {
// 添加作者名称
builder.author(author)
// 启用swagger
.enableSwagger()
// 指定输出目录
.outputDir(outputDir + "/src/main/java");
})
.packageConfig(builder -> {
builder.entity(entity)// 实体类包名
// TODO 父包名如果为空将下面子包名必须写全部 否则就只需写子包名
.parent("cn.bunny.service.admin")
.controller("controller")// 控制层包名
.mapper("mapper")// mapper层包名
.service("service")// service层包名
.serviceImpl("service.impl")// service实现类包名
// 自定义mapper.xml文件输出目录
.pathInfo(Collections.singletonMap(OutputFile.xml, outputDir + "/src/main/resources/mapper"));
})
.strategyConfig(builder -> {
// 设置要生成的表名
builder.addInclude(tableName)
//.addTablePrefix("sys_")// TODO 设置表前缀过滤
.entityBuilder()
.enableLombok()
.enableChainModel()
.naming(NamingStrategy.underline_to_camel)// 数据表映射实体命名策略默认下划线转驼峰underline_to_camel
.columnNaming(NamingStrategy.underline_to_camel)// 表字段映射实体属性命名规则默认null不指定按照naming执行
.idType(IdType.AUTO)// TODO 添加全局主键类型
.formatFileName("%s")// 格式化实体名称%s取消首字母I,
.mapperBuilder()
.mapperAnnotation(Mapper.class)// 开启mapper注解
.enableBaseResultMap()// 启用xml文件中的BaseResultMap 生成
.enableBaseColumnList()// 启用xml文件中的BaseColumnList
.formatMapperFileName("%sMapper")// 格式化Dao类名称
.formatXmlFileName("%sMapper")// 格式化xml文件名称
.serviceBuilder()
.formatServiceFileName("%sService")// 格式化 service 接口文件名称
.formatServiceImplFileName("%sServiceImpl")// 格式化 service 接口文件名称
.controllerBuilder()
.enableRestStyle();
})
// .injectionConfig(consumer -> {
// Map<String, String> customFile = new HashMap<>();
// // 配置DTO需要的话但是需要有能配置Dto的模板引擎比如freemarker但是这里我们用的VelocityEngine因此不多作介绍
// customFile.put(outputDir, "/src/main/resources/templates/entityDTO.java.ftl");
// consumer.customFile(customFile);
// })
.execute();
}
}

View File

@ -0,0 +1,57 @@
package cn.bunny.common.generator;
public class OldCodeGet {
public static void main(String[] args) {
// // 1创建代码生成器
// AutoGenerator mpg = new AutoGenerator();
//
// // 2全局配置
// // 全局配置
// GlobalConfig gc = new GlobalConfig();
// // TODO 需要修改路径名称
// gc.setOutputDir("F:\\web项目\\Bunny-Cli\\Java\\java-template\\service" + "/src/main/java");
// gc.setServiceName("%sService"); // 去掉Service接口的首字母I
// gc.setAuthor("bunny");
// gc.setOpen(false);
// mpg.setGlobalConfig(gc);
//
// // 3数据源配置
// DataSourceConfig dsc = new DataSourceConfig();
// // TODO 需要修改数据库
// dsc.setUrl("jdbc:mysql://106.15.251.123:3305/guigu-oa?serverTimezone=GMT%2B8&useSSL=false&characterEncoding=utf-8&allowPublicKeyRetrieval=true");
// dsc.setDriverName("com.mysql.cj.jdbc.Driver");
// dsc.setUsername("root");
// dsc.setPassword("02120212");
// dsc.setDbType(DbType.MYSQL);
// mpg.setDataSource(dsc);
//
// // 4包配置
// PackageConfig pc = new PackageConfig();
// pc.setParent("cn.bunny");
// // TODO 需要修改模块名
// pc.setModuleName("service");
// pc.setController("controller");
// pc.setService("service");
// pc.setMapper("mapper");
// mpg.setPackageInfo(pc);
//
// // 5策略配置
// StrategyConfig strategy = getStrategyConfig();
// mpg.setStrategy(strategy);
//
// // 6执行
// mpg.execute();
// }
//
// private static StrategyConfig getStrategyConfig() {
// StrategyConfig strategy = new StrategyConfig();
// // TODO 要生成的表
// strategy.setInclude("sys_menu", "sys_role_menu");
// strategy.setNaming(NamingStrategy.underline_to_camel);// 数据库表映射到实体的命名策略
// strategy.setColumnNaming(NamingStrategy.underline_to_camel);// 数据库表字段映射到实体的命名策略
// strategy.setEntityLombokModel(true); // lombok 模型 @Accessors(chain = true) setter链式操作
// strategy.setRestControllerStyle(true); // restful api风格控制器
// strategy.setControllerMappingHyphenStyle(true); // url中驼峰转连字符
// return strategy;
}
}

View File

@ -0,0 +1,41 @@
package cn.bunny.common.result.constant;
import lombok.Data;
/**
* 信息提示常量类
*/
@Data
public class CommonMessageConstant {
public static final String PASSWORD_ERROR = "密码错误";
public static final String OLD_PASSWORD_ERROR = "旧密码不匹配";
public static final String OLD_PASSWORD_SAME_NEW_PASSWORD = "旧密码与新密码相同";
public static final String ACCOUNT_NOT_FOUND = "账号不存在";
public static final String ACCOUNT_LOCKED = "账号被锁定";
public static final String UNKNOWN_ERROR = "未知错误";
public static final String USER_NOT_LOGIN = "用户未登录";
public static final String USER_TOKEN_OUT_OF_DATE = "用户登录过期";
public static final String LOGIN_FAILED = "登录失败";
public static final String UPLOAD_FAILED = "文件上传失败";
public static final String PASSWORD_EDIT_FAILED = "密码修改失败";
public static final String ALREADY_EXISTS = "已存在";
public static final String REQUEST_NOT_EMPTY = "请求不为空";
public static final String UPDATE_ID_IS_NOT_EMPTY = "删除id不能为空";
public static final String DELETE_ID_IS_NOT_EMPTY = "修改id不能为空";
public static final String MENU_IS_NOT_EXIST = "菜单不存在";
public static final String SAVE_DTO_IS_NULL = "添加参数不能为空";
public static final String UPDATE_DTO_IS_NULL = "修改参数不能为空";
public static final String FIND_ID_IS_NOT_EMPTY = "查询ID不能为空";
public static final String MESSAGE_CODE_NOT_PASS = "短信验证码未过期";
public static final String MESSAGE_CODE_UNAUTHORIZED = "短信验证码未授权,请联系管理员";
public static final String VERIFICATION_CODE_ERROR = "验证码错误";
public static final String USER_DOES_NOT_EXIST = "用户不存在";
public static final String USER_DOES_IS_EXIST = "用户已存在";
public static final String VERIFICATION_CODE_IS_EMPTY = "请先发送验证码";
public static final String LOGIN_DTO_IS_EMPTY = "登录参数不能为空";
public static final String TOKEN_IS_EMPTY = "token为空";
public static final String DATA_IS_EMPTY = "数据为空";
public static final String USERNAME_NOT_EMPTY = "用户名不能为空";
public static final String PASSWORD_NOT_EMPTY = "密码不能为空";
public static final String SERVER_ERROR = "密码不能为空";
}

View File

@ -0,0 +1,16 @@
package cn.bunny.common.result.constant;
import lombok.Data;
@Data
public class ExceptionConstant {
public static final String USER_NOT_FOUND = "用户不存在";
public static final String USERNAME_IS_EMPTY = "用户名不能为空";
public static final String PASSWORD_ERROR = "密码错误";
public static final String PASSWORD_IS_EMPTY = "密码不能为空";
public static final String CAPTCHA_IS_EMPTY = "提交验证码不能为空";
public static final String KEY_IS_EMPTY = "验证码key不能为空";
public static final String VERIFICATION_CODE_DOES_NOT_MATCH = "验证码不匹配";
public static final String VERIFICATION_CODE_IS_EMPTY = "验证码失效或不存在";
}

View File

@ -0,0 +1,11 @@
package cn.bunny.common.result.constant;
import lombok.Data;
@Data
public class LocalDateTimeConstant {
public static final String DEFAULT_DATE_FORMAT = "yyyy-MM-dd";
public static final String DEFAULT_DATE_TIME_FORMAT = "yyyy-MM-dd HH:mm";
public static final String DEFAULT_DATE_TIME_SECOND_FORMAT = "yyyy-MM-dd HH:mm:ss";
public static final String DEFAULT_TIME_FORMAT = "HH:mm:ss";
}

View File

@ -0,0 +1,14 @@
package cn.bunny.common.result.constant;
import lombok.Data;
/**
* 邮箱消息
*/
@Data
public class MailMessageConstant {
public static final String EMPTY_SEND_OBJECT = "空发送对象";
public static final String ADDRESS_NOT_NULL = "收件人不能为空";
public static final String TITLE_NOT_NULL = "标题不能为空";
public static final String SEND_MESSAGE_NOT_NULL = "发送消息不能为空";
}

View File

@ -0,0 +1,19 @@
package cn.bunny.common.result.constant;
import lombok.Data;
@Data
public class MinioMessageConstant {
public static final String BUCKET_EXISTS_EXCEPTION = "查询文化部对象失败";
public static final String DELETE_BUCKET_EXCEPTION = "删除文件对象失败";
public static final String GET_BUCKET_EXCEPTION = "获取文件信息失败";
public static final String QUERY_BUCKET_EXCEPTION = "查询文件信息失败";
public static final String CREATE_BUCKET_EXCEPTION = "创建文件对象失败";
public static final String UPDATE_BUCKET_EXCEPTION = "更新文件对象失败";
public static final String COMPOSE_OBJECT_EXCEPTION = "对象错误";
public static final String COPY_BUCKET_EXCEPTION = "复制文件内容失败";
public static final String DISABLE_BUCKET_EXCEPTION = "禁用文件失败";
public static final String ENABLE_BUCKET_EXCEPTION = "启用文件失败";
public static final String DOWNLOAD_BUCKET_EXCEPTION = "下载文件失败";
public static final String UPLOAD_BUCKET_EXCEPTION = "上传文件失败";
}

View File

@ -0,0 +1,18 @@
package cn.bunny.common.result.constant;
import lombok.Data;
/**
* 密码常量
*/
@Data
public class PasswordConstant {
// 默认密码
public static final String DEFAULT_PASSWORD = "123456";
// JWT密码
public static final String DEFAULT_JWT_PASSWORD = "123456";
// 默认头像
public static final String AVTAR = "https://oss.aliyuncs.com/aliyun_id_photo_bucket/default_handsome.jpg";
// 设置token过期时间
public static final long TOKEN_EXPIRATION = 365L * 24 * 60 * 60 * 1000;
}

View File

@ -0,0 +1,11 @@
package cn.bunny.common.result.constant;
import lombok.Data;
/**
* Redis用户前缀设置
*/
@Data
public class RedisUserConstant {
public static final String REDIS_CART_KEY = "user::";
}

View File

@ -0,0 +1,14 @@
package cn.bunny.common.result.constant;
import lombok.Data;
/**
* 数据库中自动填充字段
*/
@Data
public class SQLAutoFillConstant {
public static final String SET_CREATE_TIME = "setCreateTime";
public static final String SET_UPDATE_TIME = "setUpdateTime";
public static final String SET_CREATE_USER = "setCreateUser";
public static final String SET_UPDATE_USER = "setUpdateUser";
}

View File

@ -0,0 +1,12 @@
package cn.bunny.common.result.constant;
import lombok.Data;
import java.util.Arrays;
import java.util.List;
@Data
public class SecurityConstant {
public static String[] annotations = {"/", "/test/**", "/diagram-viewer/**", "/editor-app/**", "/*.html", "/admin/system/index/login", "/favicon.ico", "/swagger-resources/**", "/webjars/**", "/v3/**", "/swagger-ui.html/**", "/doc.html"};
public static List<String> annotationsList = Arrays.asList(annotations);
}

View File

@ -0,0 +1,14 @@
package cn.bunny.common.result.constant;
import lombok.Data;
/**
* 状态常量启用或者禁用
*/
@Data
public class StatusConstant {
// 启用为1
public static final Integer ENABLE = 1;
// 禁用为0
public static final Integer DISABLE = 0;
}

View File

@ -0,0 +1,8 @@
package cn.bunny.common.result.constant;
import lombok.Data;
@Data
public class UserConstant {
public static final String USER_AVATAR = "https://thirdwx.qlogo.cn/mmopen/vi_32/DYAIOgq83eoj0hHXhgJNOTSOFsS4uZs8x1ConecaVOB8eIl115xmJZcT4oCicvia7wMEufibKtTLqiaJeanU2Lpg3w/132";
}

View File

@ -0,0 +1,25 @@
package cn.bunny.common.service.properties;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
@Configuration
@ConfigurationProperties(prefix = "bunny.snowflake")
@Data
public class SnowflakeProperties {
// 数据中心id
private Long datacenterId;
// 数据中心id位数
private Long datacenterBits;
// 机器id
private Long workerId;
// 机器id位数
private Long workerBits;
// 序列id所占位数
private Long sequenceBits;
// 时间戳起始点毫秒
private Long twepoch;
// 单次批量生成id的最大数量
private Integer maxBatchCount;
}

View File

@ -0,0 +1,16 @@
package cn.bunny.dto;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class LoginDto {
private String username;
// 密码
private String password;
}

View File

@ -0,0 +1,68 @@
package cn.bunny.entity.system;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Getter;
import lombok.Setter;
import lombok.experimental.Accessors;
import java.io.Serializable;
import java.time.LocalDateTime;
/**
* <p>
* 用户信息
* </p>
*
* @author Bunny
* @since 2024-05-13
*/
@Getter
@Setter
@Accessors(chain = true)
@Schema(description = "用户信息")
public class User implements Serializable {
private static final long serialVersionUID = 1L;
@Schema(description = "用户ID")
@TableId(value = "user_id", type = IdType.AUTO)
private String userId;
@Schema(description = "昵称")
private String nickName;
@Schema(description = "邮箱")
private String email;
@Schema(description = "密码")
private String password;
@Schema(description = "0:女 1:男")
private Integer sex;
@Schema(description = "个人描述")
private String personDescription;
@Schema(description = "加入时间")
private LocalDateTime joinTime;
@Schema(description = "最后登录时间")
private LocalDateTime lastLoginTime;
@Schema(description = "最后登录IP")
private String lastLoginIp;
@Schema(description = "最后登录ip地址")
private String lastLoginIpAddress;
@Schema(description = "积分")
private Integer totalIntegral;
@Schema(description = "当前积分")
private Integer currentIntegral;
@Schema(description = "0:禁用 1:正常")
private Byte status;
}

View File

@ -0,0 +1,46 @@
package cn.bunny.entity.system;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Getter;
import lombok.Setter;
import lombok.experimental.Accessors;
import java.io.Serializable;
import java.time.LocalDateTime;
/**
* <p>
* 用户积分记录表
* </p>
*
* @author Bunny
* @since 2024-05-13
*/
@Getter
@Setter
@Accessors(chain = true)
@TableName("user_integral_record")
@Schema(description = "用户积分记录表")
public class UserIntegralRecord implements Serializable {
private static final long serialVersionUID = 1L;
@Schema(description = "记录ID")
@TableId(value = "record_id", type = IdType.AUTO)
private Integer recordId;
@Schema(description = "用户ID")
private String userId;
@Schema(description = "操作类型")
private Byte operType;
@Schema(description = "积分")
private Integer integral;
@Schema(description = "创建时间")
private LocalDateTime createTime;
}

View File

@ -0,0 +1,47 @@
package cn.bunny.entity.system;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Getter;
import lombok.Setter;
import lombok.experimental.Accessors;
import java.io.Serializable;
import java.time.LocalDateTime;
/**
* <p>
*
* </p>
*
* @author Bunny
* @since 2024-05-13
*/
@Getter
@Setter
@Accessors(chain = true)
@TableName("user_role")
@Schema(description = "UserRole对象")
public class UserRole implements Serializable {
private static final long serialVersionUID = 1L;
@TableId(value = "id", type = IdType.AUTO)
private String id;
private String userId;
private String roleName;
private String description;
private String roleCode;
@Schema(description = "创建时间")
private LocalDateTime createTime;
@Schema(description = "更新时间")
private LocalDateTime updateTime;
}

View File

@ -0,0 +1,20 @@
package cn.bunny.vo.system;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Schema(description = "验证码响应结果实体类")
public class ValidateCodeVo {
@Schema(description = "验证码key")
private String codeKey; // 验证码的key
@Schema(description = "验证码value")
private String codeValue; // 图片验证码对应的字符串数据
}

View File

@ -0,0 +1,37 @@
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>cn.bunny</groupId>
<artifactId>module</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<artifactId>spring-security</artifactId>
<packaging>jar</packaging>
<name>spring-security</name>
<url>https://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>cn.bunny</groupId>
<artifactId>service-utils</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<!-- spring-security -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<!-- spring-security-test -->
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-test</artifactId>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,86 @@
package cn.bunny.security.config;
import cn.bunny.common.result.constant.SecurityConstant;
import cn.bunny.security.custom.CustomPasswordEncoder;
import cn.bunny.security.filter.TokenAuthenticationFilter;
import cn.bunny.security.filter.TokenLoginFilterService;
import cn.bunny.security.handelr.SecurityAccessDeniedHandler;
import cn.bunny.security.handelr.SecurityAuthenticationEntryPoint;
import cn.bunny.security.service.CustomAuthorizationManagerService;
import cn.bunny.security.service.CustomUserDetailsService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
import org.springframework.security.core.session.SessionRegistry;
import org.springframework.security.core.session.SessionRegistryImpl;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.util.matcher.RegexRequestMatcher;
@Configuration
@EnableWebSecurity
@EnableMethodSecurity
public class WebSecurityConfig {
@Autowired
private RedisTemplate<String, Object> redisTemplate;
@Autowired
private CustomUserDetailsService customUserDetailsService;
@Autowired
private CustomPasswordEncoder customPasswordEncoder;
@Autowired
private CustomAuthorizationManagerService customAuthorizationManager;
@Autowired
private AuthenticationConfiguration authenticationConfiguration;
@Bean
public SecurityFilterChain filterChain(HttpSecurity httpSecurity) throws Exception {
httpSecurity
// 前端段分离不需要---禁用明文验证
.httpBasic(AbstractHttpConfigurer::disable)
// 前端段分离不需要---禁用默认登录页
.formLogin(AbstractHttpConfigurer::disable)
// 前端段分离不需要---禁用退出页
.logout(AbstractHttpConfigurer::disable)
// 前端段分离不需要---csrf攻击
.csrf(AbstractHttpConfigurer::disable)
// 跨域访问权限如果需要可以关闭后自己配置跨域访问
.cors(AbstractHttpConfigurer::disable)
// 前后端分离不需要---因为是无状态的
.sessionManagement(AbstractHttpConfigurer::disable)
// 前后端分离不需要---记住我e -> e.rememberMeParameter("rememberBunny").rememberMeCookieName("rememberBunny").key("BunnyKey")
.rememberMe(AbstractHttpConfigurer::disable)
.authorizeHttpRequests(authorize -> {
// 如果访问路径有下面的不需要访问权限
authorize.requestMatchers(SecurityConstant.annotations).permitAll();
// 有样式文件不需要访问权限
authorize.requestMatchers(RegexRequestMatcher.regexMatcher("^\\S*[css|js]$")).permitAll();
// 上面都不是需要鉴权访问
authorize.anyRequest().access(customAuthorizationManager);
})
.exceptionHandling(exception -> {
// 请求未授权接口
exception.authenticationEntryPoint(new SecurityAuthenticationEntryPoint());
// 没有权限访问
exception.accessDeniedHandler(new SecurityAccessDeniedHandler());
})
// 自定义过滤器
.addFilterBefore(new TokenAuthenticationFilter(redisTemplate), UsernamePasswordAuthenticationFilter.class)
.addFilterAt(new TokenLoginFilterService(authenticationConfiguration, redisTemplate, customUserDetailsService), UsernamePasswordAuthenticationFilter.class)
// 自定义密码加密器和用户登录
.passwordManagement(customPasswordEncoder).userDetailsService(customUserDetailsService);
return httpSecurity.build();
}
@Bean
public SessionRegistry sessionRegistry() {
return new SessionRegistryImpl();
}
}

View File

@ -0,0 +1,28 @@
package cn.bunny.security.custom;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.Customizer;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configurers.PasswordManagementConfigurer;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.util.DigestUtils;
/**
* 自定义密码加密比对
*/
@Configuration
public class CustomPasswordEncoder implements PasswordEncoder, Customizer<PasswordManagementConfigurer<HttpSecurity>> {
@Override
public String encode(CharSequence rawPassword) {
return DigestUtils.md5DigestAsHex(rawPassword.toString().getBytes());
}
@Override
public boolean matches(CharSequence rawPassword, String encodedPassword) {
return encodedPassword.matches(DigestUtils.md5DigestAsHex(rawPassword.toString().getBytes()));
}
@Override
public void customize(PasswordManagementConfigurer<HttpSecurity> httpSecurityPasswordManagementConfigurer) {
}
}

View File

@ -0,0 +1,22 @@
package cn.bunny.security.custom;
import lombok.Getter;
import lombok.Setter;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.User;
import java.util.Collection;
/**
* 重写自带的User
*/
@Getter
@Setter
public class CustomUser extends User {
private cn.bunny.entity.system.User user;
public CustomUser(cn.bunny.entity.system.User user, Collection<? extends GrantedAuthority> authorities) {
super(user.getEmail(), user.getPassword(), authorities);
this.user = user;
}
}

View File

@ -0,0 +1,74 @@
package cn.bunny.security.filter;
import cn.bunny.common.service.context.BaseContext;
import cn.bunny.common.service.utils.JwtHelper;
import com.alibaba.fastjson2.JSON;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.util.StringUtils;
import org.springframework.web.filter.OncePerRequestFilter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
public class TokenAuthenticationFilter extends OncePerRequestFilter {
private final RedisTemplate<String, Object> redisTemplate;
public TokenAuthenticationFilter(RedisTemplate<String, Object> redisTemplate) {
this.redisTemplate = redisTemplate;
}
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws ServletException, IOException {
String token = request.getHeader("token");
// login请求就没token直接放行因为后边有其他的过滤器
if (token == null) {
doFilter(request, response, chain);
return;
}
// 如果是登录接口直接放行
UsernamePasswordAuthenticationToken authentication = getAuthentication(request);
SecurityContextHolder.getContext().setAuthentication(authentication);
chain.doFilter(request, response);
}
private UsernamePasswordAuthenticationToken getAuthentication(HttpServletRequest request) {
// 请求头是否有token
String token = request.getHeader("token");
if (StringUtils.hasText(token)) {
String username = JwtHelper.getUserName(token);
if (StringUtils.hasText(username)) {
// 当前用户信息放到ThreadLocal里面
BaseContext.setUserId(JwtHelper.getUserId(token));
BaseContext.setUsername(username);
// 通过username从redis获取权限数据
String authString = (String) redisTemplate.opsForValue().get(username);
// 把redis获取字符串权限数据转换要求集合类型 List<SimpleGrantedAuthority>
if (StringUtils.hasText(authString)) {
List<Map> maplist = JSON.parseArray(authString, Map.class);
System.out.println(maplist);
List<SimpleGrantedAuthority> authList = new ArrayList<>();
for (Map map : maplist) {
String authority = (String) map.get("authority");
authList.add(new SimpleGrantedAuthority(authority));
}
return new UsernamePasswordAuthenticationToken(username, null, authList);
} else {
return new UsernamePasswordAuthenticationToken(username, null, new ArrayList<>());
}
}
}
return null;
}
}

View File

@ -0,0 +1,84 @@
package cn.bunny.security.filter;
import cn.bunny.common.result.enums.ResultCodeEnum;
import cn.bunny.common.result.utils.Result;
import cn.bunny.common.service.utils.ResponseUtil;
import cn.bunny.dto.LoginDto;
import cn.bunny.security.handelr.SecurityAuthenticationFailureHandler;
import cn.bunny.security.handelr.SecurityAuthenticationSuccessHandler;
import cn.bunny.security.service.CustomUserDetailsService;
import cn.bunny.vo.system.LoginVo;
import com.fasterxml.jackson.databind.ObjectMapper;
import jakarta.servlet.FilterChain;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import org.springframework.util.StringUtils;
import java.io.IOException;
/**
* 由于SpringSecurity的登录只能是表单形式 并且用户名密码需要时usernamepassword,可以通过继承 UsernamePasswordAuthenticationFilter 获取登录请求的参数
* 再去设置到 UsernamePasswordAuthenticationToken 来改变请求传参方式参数名等 或者也可以在登录的时候加入其他参数等等
* 也可以在这里添加验证码短信等的验证
*/
public class TokenLoginFilterService extends UsernamePasswordAuthenticationFilter {
private final RedisTemplate<String, Object> redisTemplate;
private final CustomUserDetailsService customUserDetailsService;
private LoginDto loginDto;
// 构造方法
public TokenLoginFilterService(AuthenticationConfiguration authenticationConfiguration, RedisTemplate<String, Object> redisTemplate, CustomUserDetailsService customUserDetailsService) throws Exception {
this.setAuthenticationSuccessHandler(new SecurityAuthenticationSuccessHandler());
this.setAuthenticationFailureHandler(new SecurityAuthenticationFailureHandler());
this.setPostOnly(false);
// 指定登录接口及提交方式可以指定任意路径
this.setRequiresAuthenticationRequestMatcher(new AntPathRequestMatcher("/*/login", "POST"));
this.setAuthenticationManager(authenticationConfiguration.getAuthenticationManager());
this.redisTemplate = redisTemplate;
this.customUserDetailsService = customUserDetailsService;
}
// 登录认证
// 获取输入的用户名和密码调用方法认证
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
try {
// 获取用户信息
loginDto = new ObjectMapper().readValue(request.getInputStream(), LoginDto.class);
// 封装对象
Authentication authenticationToken = new UsernamePasswordAuthenticationToken(loginDto.getUsername(), loginDto.getPassword());
// 调用方法
return this.getAuthenticationManager().authenticate(authenticationToken);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
// 认证成功调用方法
protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication auth) {
// 返回登录信息
LoginVo login = customUserDetailsService.login(loginDto);
ResponseUtil.out(response, Result.success(login));
}
// 认证失败调用方法
protected void unsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response, AuthenticationException failed) {
// 用户名为空
if (!StringUtils.hasText(loginDto.getUsername())) {
ResponseUtil.out(response, Result.error(ResultCodeEnum.USERNAME_NOT_EMPTY));
}
// 密码为空
if (!StringUtils.hasText(loginDto.getPassword())) {
ResponseUtil.out(response, Result.error(ResultCodeEnum.PASSWORD_NOT_EMPTY));
}
// 抛出异常
ResponseUtil.out(response, Result.error(null, ResultCodeEnum.LOGIN_ERROR));
}
}

View File

@ -0,0 +1,26 @@
package cn.bunny.security.handelr;
import cn.bunny.common.result.enums.ResultCodeEnum;
import cn.bunny.common.result.utils.Result;
import com.alibaba.fastjson2.JSON;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.SneakyThrows;
import org.springframework.security.access.AccessDeniedException;
/**
* 没有权限访问
*/
public class SecurityAccessDeniedHandler implements org.springframework.security.web.access.AccessDeniedHandler {
@SneakyThrows
@Override
public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException) {
Result<Object> result = Result.error(ResultCodeEnum.FAIL_NO_ACCESS_DENIED);
Object json = JSON.toJSON(result);
// 返回响应
response.setContentType("application/json;charset=UTF-8");
response.getWriter().println(json);
}
}

View File

@ -0,0 +1,39 @@
package cn.bunny.security.handelr;
import cn.bunny.common.result.utils.Result;
import cn.bunny.common.result.enums.ResultCodeEnum;
import com.alibaba.fastjson2.JSON;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.AuthenticationEntryPoint;
import java.io.IOException;
/**
* 请求未认证接口
*/
@Slf4j
public class SecurityAuthenticationEntryPoint implements AuthenticationEntryPoint {
@Override
public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException {
String token = response.getHeader("token");
String message = authException.getMessage();
// 创建结果对象
Result<Object> result;
if (token == null) {
result = Result.error(new Object(), ResultCodeEnum.LOGIN_AUTH);
log.info("请求未登录接口:{}用户id{}", message, null);
} else {
result = Result.error(new Object(), ResultCodeEnum.LOGGED_IN_FROM_ANOTHER_DEVICE);
log.info("请求未授权接口:{}用户id{}", message, token);
}
// 返回响应
response.setContentType("application/json;charset=UTF-8");
response.getWriter().println(JSON.toJSON(result));
}
}

View File

@ -0,0 +1,26 @@
package cn.bunny.security.handelr;
import cn.bunny.common.result.utils.Result;
import com.alibaba.fastjson2.JSON;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.security.core.AuthenticationException;
import java.io.IOException;
public class SecurityAuthenticationFailureHandler implements org.springframework.security.web.authentication.AuthenticationFailureHandler {
@Override
public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException {
// 错误消息
String localizedMessage = exception.getLocalizedMessage();
Result<String> result = Result.error(localizedMessage);
// 转成JSON
Object json = JSON.toJSON(result);
// 返回响应
response.setContentType("application/json;charset=UTF-8");
response.getWriter().println(json);
}
}

View File

@ -0,0 +1,26 @@
package cn.bunny.security.handelr;
import cn.bunny.common.result.utils.Result;
import com.alibaba.fastjson2.JSON;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.security.core.Authentication;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import java.io.IOException;
/**
* 登录成功
*/
public class SecurityAuthenticationSuccessHandler implements AuthenticationSuccessHandler {
@Override
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException {
// 获取用户身份信息
Object principal = authentication.getPrincipal();
Result<Object> result = Result.success(principal);
// 返回
response.setContentType("application/json;charset=UTF-8");
response.getWriter().println(JSON.toJSON(result));
}
}

View File

@ -0,0 +1,7 @@
package cn.bunny.security.service;
import org.springframework.security.authorization.AuthorizationManager;
import org.springframework.security.web.access.intercept.RequestAuthorizationContext;
public interface CustomAuthorizationManagerService extends AuthorizationManager<RequestAuthorizationContext> {
}

View File

@ -0,0 +1,23 @@
package cn.bunny.security.service;
import cn.bunny.dto.LoginDto;
import cn.bunny.vo.system.LoginVo;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
public interface CustomUserDetailsService extends UserDetailsService {
/**
* 根据用户名获取用户对象获取不到直接抛异常
*/
@Override
UserDetails loadUserByUsername(String username) throws UsernameNotFoundException;
/**
* 前台用户登录接口
*
* @param loginDto 登录参数
* @return 登录后结果返回
*/
LoginVo login(LoginDto loginDto);
}

View File

@ -0,0 +1,14 @@
package cn.bunny.service.gateway.task;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
@Component
@Slf4j
public class TemplateTask {
@Scheduled(cron = "0/1 5 * * * ?")
public void templateTask() {
log.info("定时任务执行...");
}
}

View File

@ -0,0 +1,21 @@
FROM openjdk:21
MAINTAINER bunny
#系统编码
ENV LANG=C.UTF-8 LC_ALL=C.UTF-8
# 设置时区,构建镜像时执行的命令
RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
RUN echo "Asia/Shanghai" > /etc/timezone
# 设定工作目录
WORKDIR /home/bunny
# 复制jar包
COPY target/*.jar /home/bunny/app.jar
#启动容器时的进程
ENTRYPOINT ["java","-jar","/home/bunny/app.jar"]
#暴露 8800 端口
EXPOSE 8800

View File

@ -0,0 +1,101 @@
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>cn.bunny</groupId>
<artifactId>service</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<artifactId>service-admin</artifactId>
<packaging>jar</packaging>
<name>service-admin</name>
<url>https://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<docker.repostory>192.168.3.98:1100</docker.repostory>
<docker.host>192.168.3.98:2375</docker.host>
<docker.registry.name>bunny-admin</docker.registry.name>
</properties>
<dependencies>
<dependency>
<groupId>cn.bunny</groupId>
<artifactId>spring-security</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<!-- service-utils -->
<dependency>
<groupId>cn.bunny</groupId>
<artifactId>service-utils</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>cn.bunny</groupId>
<artifactId>module-mail</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>cn.bunny</groupId>
<artifactId>module-minio</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<!-- asp 切面 -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<skip>true</skip>
</configuration>
</plugin>
<plugin>
<groupId>com.spotify</groupId>
<artifactId>docker-maven-plugin</artifactId>
<version>1.2.2</version>
<!--将插件绑定在某个phase执行-->
<executions>
<execution>
<id>build-image</id>
<!--将插件绑定在package这个phase(阶段)上。也就是说用户只需执行mvn package就会自动执行mvn docker:build-->
<phase>package</phase>
<goals>
<goal>build</goal>
<goal>push</goal>
</goals>
</execution>
</executions>
<configuration>
<serverId>harbor</serverId>
<registryUrl>http://${docker.repostory}</registryUrl>
<!-- 配置docker主机地址 -->
<dockerHost>http://${docker.host}</dockerHost>
<!--指定生成的镜像名-->
<imageName>
${docker.repostory}/${docker.registry.name}/${project.artifactId}:${project.version}
</imageName>
<!-- 指定 dockerfile 路径-->
<dockerDirectory>${project.basedir}</dockerDirectory>
<!-- 是否跳过docker构建 -->
<skipDockerBuild>false</skipDockerBuild>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@ -0,0 +1,22 @@
package cn.bunny.service.admin;
import lombok.extern.slf4j.Slf4j;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.scheduling.annotation.EnableScheduling;
@ComponentScan(basePackages = {"cn.bunny"})
@MapperScan("cn.bunny.service.admin.mapper")
@EnableScheduling// 定时任务
@EnableCaching// 开启缓存注解
@SpringBootApplication
@Slf4j
public class ServiceAdminApplication {
public static void main(String[] args) {
log.info("ServiceApplication启动...");
SpringApplication.run(ServiceAdminApplication.class, args);
}
}

View File

@ -0,0 +1,19 @@
bunny:
datasource:
host: 106.15.251.123
port: 3305
sqlData: bunny_docs
username: root
password: "02120212"
redis:
host: 47.120.65.66
port: 6379
database: 3
password: "02120212"
minio:
endpointUrl: "http://129.211.31.58:9000"
bucket-name: ssyx
accessKey: bunny
secretKey: "02120212"

View File

@ -0,0 +1,63 @@
server:
port: 8802
spring:
profiles:
active: dev
application:
name: service-admin
datasource:
type: com.zaxxer.hikari.HikariDataSource
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://${bunny.datasource.host}:${bunny.datasource.port}/${bunny.datasource.sqlData}?serverTimezone=GMT%2B8&useSSL=false&characterEncoding=utf-8&allowPublicKeyRetrieval=true
username: ${bunny.datasource.username}
password: ${bunny.datasource.password}
data:
redis:
host: ${bunny.redis.host}
port: ${bunny.redis.port}
database: ${bunny.redis.database}
password: ${bunny.redis.password}
lettuce:
pool:
max-active: 20 #最大连接数
max-wait: -1 #最大阻塞等待时间(负数表示没限制)
max-idle: 5 #最大空闲
min-idle: 0 #最小空闲
jackson:
date-format: yyyy-MM-dd HH:mm:ss
time-zone: GMT+8
mybatis-plus:
mapper-locations: classpath:mapper/*.xml
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl # 查看日志
logging:
level:
cn.bunny.service.mapper: debug
cn.bunny.service.controller: info
cn.bunny.service.service: info
pattern:
dateformat: HH:mm:ss:SSS
file:
path: "logs/${spring.application.name}"
bunny:
minio:
endpointUrl: ${bunny.minio.endpointUrl}
accessKey: ${bunny.minio.accessKey}
secretKey: ${bunny.minio.secretKey}
bucket-name: ${bunny.minio.bucket-name}
snowflake:
datacenterBits: 5 # 数据中心id位数
workerBits: 5 # 机器id位数
sequenceBits: 12 # 序列id所占位数
datacenterId: 1 # 数据中心id,范围0-2^5-1
workerId: 1 # 机器id,范围0-2^5-1
twepoch: 1704038400000 # 时间戳起始点2024-01-01 00::00:00 的毫秒数)
maxBatchCount: 100000 #单次批量生成id的最大数量 默认10万

View File

@ -0,0 +1,16 @@
-----------------▄██-█▄---------
-----------------███▄██▄--------
-----------------███████--------
-----------------▀███████-------
-------------------██████▄▄-----
-------------------█████████▄---
-------------------██████▄████--
-------▄███████████████████████-
-----▄███████████████████████▀--
---▄██████████████████████------
---███████████████████████------
---███████████████████████------
-▄▄██████████████████████▀------
-█████████████████▀█████--------
-▀██████████████▀▀-▀█████▄------
-------▀▀▀▀▀▀▀▀▀------▀▀▀▀------

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

View File

@ -0,0 +1,61 @@
<?xml version="1.0" encoding="UTF-8" ?>
<configuration debug="false" xmlns="http://ch.qos.logback/xml/ns/logback"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://ch.qos.logback/xml/ns/logback
https://raw.githubusercontent.com/enricopulatzo/logback-XSD/master/src/main/xsd/logback.xsd">
<appender name="STOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>
%cyan([%thread]) %yellow(%-5level) %green(%logger{100}).%boldRed(%method)-%boldMagenta(%line) - %blue(%msg%n)
</pattern>
</encoder>
</appender>
<!-- additivity:false 禁止重复打印日志 -->
<!-- 让SpringBoot内部日志ERROR级别 减少日志输出 -->
<logger name="org.springframework" level="ERROR" additivity="false">
<appender-ref ref="STOUT"/>
</logger>
<!-- 让mybatis整合包日志ERROR 减少日志输出 -->
<logger name="org.mybatis" level="ERROR" additivity="false">
<appender-ref ref="STOUT"/>
</logger>
<!-- 让ibatis 日志ERROR 减少日志输出 -->
<logger name="org.apache.ibatis" level="ERROR" additivity="false">
<appender-ref ref="STOUT"/>
</logger>
<!-- 让 tomcat包打印日志 日志ERROR 减少日志输出 -->
<logger name="org.apache" level="ERROR" additivity="false">
<appender-ref ref="STOUT"/>
</logger>
<!-- 我们自己开发的程序为DEBUG -->
<logger name="com.redpig" level="DEBUG" additivity="false">
<appender-ref ref="STOUT"/>
</logger>
<logger name="com.baomidou" level="ERROR" additivity="false">
<appender-ref ref="STOUT"/>
</logger>
<logger name="com.zaxxer" level="ERROR" additivity="false">
<appender-ref ref="STOUT"/>
</logger>
<!-- Activiti日志 -->
<logger name="org.activiti" level="ERROR" />
<logger name="org.activiti.engine.impl.persistence.entity" level="DEBUG" />
<logger name="_org.springframework" level="ERROR" />
<logger name="springfox.documentation" level="ERROR" />
<!-- root级别开debug 子目录根据需要关闭 -->
<root level="DEBUG">
<appender-ref ref="STOUT"/>
</root>
</configuration>

View File

@ -0,0 +1,21 @@
FROM openjdk:21
MAINTAINER bunny
#系统编码
ENV LANG=C.UTF-8 LC_ALL=C.UTF-8
# 设置时区,构建镜像时执行的命令
RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
RUN echo "Asia/Shanghai" > /etc/timezone
# 设定工作目录
WORKDIR /home/bunny
# 复制jar包
COPY target/*.jar /home/bunny/app.jar
#启动容器时的进程
ENTRYPOINT ["java","-jar","/home/bunny/app.jar"]
#暴露 8800 端口
EXPOSE 8800

114
service/service-web/pom.xml Normal file
View File

@ -0,0 +1,114 @@
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>cn.bunny</groupId>
<artifactId>service</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<artifactId>service-web</artifactId>
<packaging>jar</packaging>
<name>service-main</name>
<url>https://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<docker.repostory>192.168.3.98:1100</docker.repostory>
<docker.host>192.168.3.98:2375</docker.host>
<docker.registry.name>bunny-web</docker.registry.name>
</properties>
<dependencies>
<dependency>
<groupId>cn.bunny</groupId>
<artifactId>spring-security</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<!-- service-utils -->
<dependency>
<groupId>cn.bunny</groupId>
<artifactId>service-utils</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>cn.bunny</groupId>
<artifactId>module-mail</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>cn.bunny</groupId>
<artifactId>module-minio</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<!-- asp 切面 -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
</dependency>
<!-- loadbalancer依赖 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-loadbalancer</artifactId>
<version>4.1.2</version>
</dependency>
<!-- 服务注册 -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
<version>2023.0.0.0-RC1</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<skip>true</skip>
</configuration>
</plugin>
<plugin>
<groupId>com.spotify</groupId>
<artifactId>docker-maven-plugin</artifactId>
<version>1.2.2</version>
<!--将插件绑定在某个phase执行-->
<executions>
<execution>
<id>build-image</id>
<!--将插件绑定在package这个phase(阶段)上。也就是说用户只需执行mvn package就会自动执行mvn docker:build-->
<phase>package</phase>
<goals>
<goal>build</goal>
<goal>push</goal>
</goals>
</execution>
</executions>
<configuration>
<serverId>harbor</serverId>
<registryUrl>http://${docker.repostory}</registryUrl>
<!-- 配置docker主机地址 -->
<dockerHost>http://${docker.host}</dockerHost>
<!--指定生成的镜像名-->
<imageName>
${docker.repostory}/${docker.registry.name}/${project.artifactId}:${project.version}
</imageName>
<!-- 指定 dockerfile 路径-->
<dockerDirectory>${project.basedir}</dockerDirectory>
<!-- 是否跳过docker构建 -->
<skipDockerBuild>false</skipDockerBuild>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@ -0,0 +1,20 @@
package cn.bunny.service.web;
import lombok.extern.slf4j.Slf4j;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.ComponentScan;
@SpringBootApplication
@Slf4j
@ComponentScan(basePackages = {"cn.bunny"})
@MapperScan("cn.bunny.service.web.mapper")
@EnableCaching// 开启缓存注解
public class ServiceWebApplication {
public static void main(String[] args) {
log.info("ServiceApplication启动...");
SpringApplication.run(ServiceWebApplication.class, args);
}
}

View File

@ -0,0 +1,15 @@
package cn.bunny.service.aop.annotation;
import cn.bunny.enums.OperationType;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface AutoFill {
// 数据库操作类型
OperationType value();
}

View File

@ -0,0 +1,27 @@
package cn.bunny.service.aop.aspect;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
@Aspect
@Component
@Slf4j
public class AutoFillAspect {
@Pointcut("execution(* cn.bunny.service.*.*(..))")
public void autoFillPointcut() {
}
/**
* 之前操作
*
* @param joinPoint 参数
*/
@Before("autoFillPointcut()")
public void autoFill(JoinPoint joinPoint) {
log.info("开始进行自动填充");
}
}

View File

@ -0,0 +1,33 @@
package cn.bunny.service.web.controller;
import cn.bunny.common.result.utils.Result;
import cn.bunny.dto.LoginDto;
import cn.bunny.service.web.service.LoginService;
import cn.bunny.vo.system.LoginVo;
import cn.bunny.vo.system.ValidateCodeVo;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
@Tag(name = "登录和注册相关接口")
@RequestMapping("/api")
@RestController
public class LoginController {
@Autowired
private LoginService loginService;
@Operation(summary = "登录接口", description = "前台用户登录接口")
@PostMapping("login")
public Result<LoginVo> login(@RequestBody LoginDto loginDto) {
LoginVo vo = loginService.login(loginDto);
return Result.success(vo);
}
@Operation(summary = "生成验证码", description = "生成验证码")
@GetMapping("checkCode")
public Result<ValidateCodeVo> checkCode() {
ValidateCodeVo vo = loginService.checkCode();
return Result.success(vo);
}
}

View File

@ -0,0 +1,18 @@
package cn.bunny.service.web.controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* <p>
* 用户信息 前端控制器
* </p>
*
* @author Bunny
* @since 2024-05-13
*/
@RestController
@RequestMapping("/user")
public class UserController {
}

View File

@ -0,0 +1,18 @@
package cn.bunny.service.web.controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* <p>
* 用户积分记录表 前端控制器
* </p>
*
* @author Bunny
* @since 2024-05-13
*/
@RestController
@RequestMapping("/userIntegralRecord")
public class UserIntegralRecordController {
}

View File

@ -0,0 +1,18 @@
package cn.bunny.service.web.controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* <p>
* 前端控制器
* </p>
*
* @author Bunny
* @since 2024-05-13
*/
@RestController
@RequestMapping("/userRole")
public class UserRoleController {
}

View File

@ -0,0 +1,18 @@
package cn.bunny.service.web.mapper;
import cn.bunny.entity.system.UserIntegralRecord;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
/**
* <p>
* 用户积分记录表 Mapper 接口
* </p>
*
* @author Bunny
* @since 2024-05-13
*/
@Mapper
public interface UserIntegralRecordMapper extends BaseMapper<UserIntegralRecord> {
}

View File

@ -0,0 +1,27 @@
package cn.bunny.service.web.mapper;
import cn.bunny.entity.system.User;
import cn.bunny.vo.system.LoginVo;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
/**
* <p>
* 用户信息 Mapper 接口
* </p>
*
* @author Bunny
* @since 2024-05-13
*/
@Mapper
public interface UserMapper extends BaseMapper<User> {
/**
* 前台用户登录接口
*
* @param username 邮箱/昵称
* @param password Image
* @return 登录参数
*/
LoginVo login(String username, String password);
}

View File

@ -0,0 +1,18 @@
package cn.bunny.service.web.mapper;
import cn.bunny.entity.system.UserRole;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
/**
* <p>
* Mapper 接口
* </p>
*
* @author Bunny
* @since 2024-05-13
*/
@Mapper
public interface UserRoleMapper extends BaseMapper<UserRole> {
}

View File

@ -0,0 +1,36 @@
package cn.bunny.service.web.security;
import cn.bunny.security.service.CustomAuthorizationManagerService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.authorization.AuthorizationDecision;
import org.springframework.security.core.Authentication;
import org.springframework.security.web.access.intercept.RequestAuthorizationContext;
import org.springframework.stereotype.Service;
import java.util.function.Supplier;
/**
* 自定义权限判断
* 判断用户有哪些权限
*/
@Service
@Slf4j
public class CustomAuthorizationManagerServiceImpl implements CustomAuthorizationManagerService {
@Override
public void verify(Supplier<Authentication> authentication, RequestAuthorizationContext requestAuthorizationContext) {
CustomAuthorizationManagerService.super.verify(authentication, requestAuthorizationContext);
}
@Override
public AuthorizationDecision check(Supplier<Authentication> authentication, RequestAuthorizationContext object) {
String token = object.getRequest().getHeader("token");
if (token == null) {
throw new AccessDeniedException("");
}
return new AuthorizationDecision(true);
}
}

View File

@ -0,0 +1,58 @@
package cn.bunny.service.web.security;
import cn.bunny.dto.LoginDto;
import cn.bunny.entity.system.User;
import cn.bunny.entity.system.UserRole;
import cn.bunny.security.custom.CustomUser;
import cn.bunny.service.web.mapper.UserMapper;
import cn.bunny.service.web.mapper.UserRoleMapper;
import cn.bunny.service.web.service.LoginService;
import cn.bunny.vo.system.LoginVo;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import java.util.List;
@Configuration
public class CustomUserDetailsService implements cn.bunny.security.service.CustomUserDetailsService {
@Autowired
private UserMapper userMapper;
@Autowired
private LoginService loginService;
@Autowired
private UserRoleMapper userRoleMapper;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
// 根据邮箱查询用户名
User user = userMapper.selectOne(Wrappers.<User>lambdaQuery().eq(User::getEmail, username));
List<UserRole> sysRoleList = userRoleMapper.selectList(null);
// 如果这次为空再试下查询昵称
if (user == null) {
user = userMapper.selectOne(Wrappers.<User>lambdaQuery().eq(User::getNickName, username));
}
// 都为空抛出异常用户不存在
if (user == null) {
throw new UsernameNotFoundException("");
}
// 查询所有的角色
List<String> roleAuthoritieList = sysRoleList.stream().map(UserRole::getRoleCode).toList();
return new CustomUser(user, AuthorityUtils.createAuthorityList(roleAuthoritieList));
}
/**
* 前台用户登录接口
*
* @param loginDto 登录参数
* @return 登录后结果返回
*/
@Override
public LoginVo login(LoginDto loginDto) {
return loginService.login(loginDto);
}
}

View File

@ -0,0 +1,24 @@
package cn.bunny.service.web.service;
import cn.bunny.dto.LoginDto;
import cn.bunny.entity.system.User;
import cn.bunny.vo.system.LoginVo;
import cn.bunny.vo.system.ValidateCodeVo;
import com.baomidou.mybatisplus.extension.service.IService;
public interface LoginService extends IService<User> {
/**
* 前台用户登录接口
*
* @param loginDto 登录参数
* @return 登录后结果返回
*/
LoginVo login(LoginDto loginDto);
/**
* 生成验证码
*
* @return 验证码生成信息
*/
ValidateCodeVo checkCode();
}

View File

@ -0,0 +1,16 @@
package cn.bunny.service.web.service;
import cn.bunny.entity.system.UserIntegralRecord;
import com.baomidou.mybatisplus.extension.service.IService;
/**
* <p>
* 用户积分记录表 服务类
* </p>
*
* @author Bunny
* @since 2024-05-13
*/
public interface UserIntegralRecordService extends IService<UserIntegralRecord> {
}

View File

@ -0,0 +1,16 @@
package cn.bunny.service.web.service;
import cn.bunny.entity.system.UserRole;
import com.baomidou.mybatisplus.extension.service.IService;
/**
* <p>
* 服务类
* </p>
*
* @author Bunny
* @since 2024-05-13
*/
public interface UserRoleService extends IService<UserRole> {
}

View File

@ -0,0 +1,16 @@
package cn.bunny.service.web.service;
import cn.bunny.entity.system.User;
import com.baomidou.mybatisplus.extension.service.IService;
/**
* <p>
* 用户信息 服务类
* </p>
*
* @author Bunny
* @since 2024-05-13
*/
public interface UserService extends IService<User> {
}

View File

@ -0,0 +1,69 @@
package cn.bunny.service.web.service.impl;
import cn.bunny.common.result.constant.CommonMessageConstant;
import cn.bunny.common.service.utils.EmptyUtil;
import cn.bunny.common.service.utils.JwtHelper;
import cn.bunny.dto.LoginDto;
import cn.bunny.entity.system.User;
import cn.bunny.service.web.mapper.UserMapper;
import cn.bunny.service.web.service.LoginService;
import cn.bunny.vo.system.LoginVo;
import cn.bunny.vo.system.ValidateCodeVo;
import cn.hutool.captcha.CaptchaUtil;
import cn.hutool.captcha.CircleCaptcha;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.DigestUtils;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
@Service
public class LoginServiceImpl extends ServiceImpl<UserMapper, User> implements LoginService {
@Autowired
private UserMapper userMapper;
@Autowired
private RedisTemplate<String, Object> redisTemplate;
/**
* 前台用户登录接口
*
* @param loginDto 登录参数
* @return 登录后结果返回
*/
@Override
public LoginVo login(LoginDto loginDto) {
// 判断用户和密码是否为空
String username = loginDto.getUsername();
EmptyUtil.isEmpty(username, CommonMessageConstant.USERNAME_NOT_EMPTY);
// 密码不能为空
EmptyUtil.isEmpty(loginDto.getPassword(), CommonMessageConstant.PASSWORD_NOT_EMPTY);
String password = DigestUtils.md5DigestAsHex(loginDto.getPassword().getBytes());
// 设置返回类型
LoginVo loginVo = userMapper.login(username, password);
String token = JwtHelper.createToken(Long.valueOf(loginVo.getUserId()), loginVo.getEmail(), 7);
loginVo.setToken(token);
return loginVo;
}
/**
* 生成验证码
*
* @return 验证码生成信息
*/
@Override
public ValidateCodeVo checkCode() {
// 生成验证码
CircleCaptcha captcha = CaptchaUtil.createCircleCaptcha(150, 48, 4, 2);
String code = captcha.getCode();
String base64Image = "data:image/png;base64," + captcha.getImageBase64();
// 存储到Redis中
String uuid = UUID.randomUUID().toString().replaceAll("-", "");
redisTemplate.opsForValue().set(uuid, code, 10, TimeUnit.MINUTES);
return ValidateCodeVo.builder().codeKey(uuid).codeValue(base64Image).build();
}
}

View File

@ -0,0 +1,20 @@
package cn.bunny.service.web.service.impl;
import cn.bunny.entity.system.UserIntegralRecord;
import cn.bunny.service.web.mapper.UserIntegralRecordMapper;
import cn.bunny.service.web.service.UserIntegralRecordService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
/**
* <p>
* 用户积分记录表 服务实现类
* </p>
*
* @author Bunny
* @since 2024-05-13
*/
@Service
public class UserIntegralRecordServiceImpl extends ServiceImpl<UserIntegralRecordMapper, UserIntegralRecord> implements UserIntegralRecordService {
}

View File

@ -0,0 +1,20 @@
package cn.bunny.service.web.service.impl;
import cn.bunny.entity.system.UserRole;
import cn.bunny.service.web.mapper.UserRoleMapper;
import cn.bunny.service.web.service.UserRoleService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
/**
* <p>
* 服务实现类
* </p>
*
* @author Bunny
* @since 2024-05-13
*/
@Service
public class UserRoleServiceImpl extends ServiceImpl<UserRoleMapper, UserRole> implements UserRoleService {
}

View File

@ -0,0 +1,20 @@
package cn.bunny.service.web.service.impl;
import cn.bunny.entity.system.User;
import cn.bunny.service.web.mapper.UserMapper;
import cn.bunny.service.web.service.UserService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
/**
* <p>
* 用户信息 服务实现类
* </p>
*
* @author Bunny
* @since 2024-05-13
*/
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
}

View File

@ -0,0 +1,24 @@
bunny:
datasource:
host: 106.15.251.123
port: 3305
sqlData: bunny_docs
username: root
password: "02120212"
redis:
host: 47.120.65.66
port: 6379
database: 3
password: "02120212"
minio:
endpointUrl: "http://129.211.31.58:9000"
bucket-name: ssyx
accessKey: bunny
secretKey: "02120212"
nacos:
server-addr: z-bunny.cn:8848
discovery:
namespace: bunnyBBS

View File

@ -0,0 +1,71 @@
server:
port: 8801
spring:
profiles:
active: dev
application:
name: service-web
datasource:
type: com.zaxxer.hikari.HikariDataSource
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://${bunny.datasource.host}:${bunny.datasource.port}/${bunny.datasource.sqlData}?serverTimezone=GMT%2B8&useSSL=false&characterEncoding=utf-8&allowPublicKeyRetrieval=true
username: ${bunny.datasource.username}
password: ${bunny.datasource.password}
data:
redis:
host: ${bunny.redis.host}
port: ${bunny.redis.port}
database: ${bunny.redis.database}
password: ${bunny.redis.password}
lettuce:
pool:
max-active: 20 #最大连接数
max-wait: -1 #最大阻塞等待时间(负数表示没限制)
max-idle: 5 #最大空闲
min-idle: 0 #最小空闲
jackson:
date-format: yyyy-MM-dd HH:mm:ss
time-zone: GMT+8
cloud:
sentinel:
log:
dir: logs/${spring.application.name}/sentinel
nacos:
discovery:
namespace: ${bunny.nacos.discovery.namespace}
server-addr: ${bunny.nacos.server-addr}
mybatis-plus:
mapper-locations: classpath:mapper/*.xml
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl # 查看日志
logging:
level:
cn.bunny.service.mapper: debug
cn.bunny.service.controller: info
cn.bunny.service.service: info
pattern:
dateformat: HH:mm:ss:SSS
file:
path: "logs/${spring.application.name}"
bunny:
minio:
endpointUrl: ${bunny.minio.endpointUrl}
accessKey: ${bunny.minio.accessKey}
secretKey: ${bunny.minio.secretKey}
bucket-name: ${bunny.minio.bucket-name}
snowflake:
datacenterBits: 5 # 数据中心id位数
workerBits: 5 # 机器id位数
sequenceBits: 12 # 序列id所占位数
datacenterId: 1 # 数据中心id,范围0-2^5-1
workerId: 1 # 机器id,范围0-2^5-1
twepoch: 1704038400000 # 时间戳起始点2024-01-01 00::00:00 的毫秒数)
maxBatchCount: 100000 #单次批量生成id的最大数量 默认10万

View File

@ -0,0 +1,16 @@
-----------------▄██-█▄---------
-----------------███▄██▄--------
-----------------███████--------
-----------------▀███████-------
-------------------██████▄▄-----
-------------------█████████▄---
-------------------██████▄████--
-------▄███████████████████████-
-----▄███████████████████████▀--
---▄██████████████████████------
---███████████████████████------
---███████████████████████------
-▄▄██████████████████████▀------
-█████████████████▀█████--------
-▀██████████████▀▀-▀█████▄------
-------▀▀▀▀▀▀▀▀▀------▀▀▀▀------

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

View File

@ -0,0 +1,61 @@
<?xml version="1.0" encoding="UTF-8" ?>
<configuration debug="false" xmlns="http://ch.qos.logback/xml/ns/logback"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://ch.qos.logback/xml/ns/logback
https://raw.githubusercontent.com/enricopulatzo/logback-XSD/master/src/main/xsd/logback.xsd">
<appender name="STOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>
%cyan([%thread]) %yellow(%-5level) %green(%logger{100}).%boldRed(%method)-%boldMagenta(%line) - %blue(%msg%n)
</pattern>
</encoder>
</appender>
<!-- additivity:false 禁止重复打印日志 -->
<!-- 让SpringBoot内部日志ERROR级别 减少日志输出 -->
<logger name="org.springframework" level="ERROR" additivity="false">
<appender-ref ref="STOUT"/>
</logger>
<!-- 让mybatis整合包日志ERROR 减少日志输出 -->
<logger name="org.mybatis" level="ERROR" additivity="false">
<appender-ref ref="STOUT"/>
</logger>
<!-- 让ibatis 日志ERROR 减少日志输出 -->
<logger name="org.apache.ibatis" level="ERROR" additivity="false">
<appender-ref ref="STOUT"/>
</logger>
<!-- 让 tomcat包打印日志 日志ERROR 减少日志输出 -->
<logger name="org.apache" level="ERROR" additivity="false">
<appender-ref ref="STOUT"/>
</logger>
<!-- 我们自己开发的程序为DEBUG -->
<logger name="com.redpig" level="DEBUG" additivity="false">
<appender-ref ref="STOUT"/>
</logger>
<logger name="com.baomidou" level="ERROR" additivity="false">
<appender-ref ref="STOUT"/>
</logger>
<logger name="com.zaxxer" level="ERROR" additivity="false">
<appender-ref ref="STOUT"/>
</logger>
<!-- Activiti日志 -->
<logger name="org.activiti" level="ERROR" />
<logger name="org.activiti.engine.impl.persistence.entity" level="DEBUG" />
<logger name="_org.springframework" level="ERROR" />
<logger name="springfox.documentation" level="ERROR" />
<!-- root级别开debug 子目录根据需要关闭 -->
<root level="DEBUG">
<appender-ref ref="STOUT"/>
</root>
</configuration>

View File

@ -0,0 +1,19 @@
<?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="cn.bunny.service.web.mapper.UserIntegralRecordMapper">
<!-- 通用查询映射结果 -->
<resultMap id="BaseResultMap" type="cn.bunny.entity.system.UserIntegralRecord">
<id column="record_id" property="recordId"/>
<result column="user_id" property="userId"/>
<result column="oper_type" property="operType"/>
<result column="integral" property="integral"/>
<result column="create_time" property="createTime"/>
</resultMap>
<!-- 通用查询结果列 -->
<sql id="Base_Column_List">
user_id, oper_type, integral, create_time
</sql>
</mapper>

View File

@ -0,0 +1,19 @@
<?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="cn.bunny.service.web.mapper.UserMapper">
<!-- 通用查询结果列 -->
<sql id="Base_Column_List">
user_id, nick_name, email, password, sex, person_description, join_time, last_login_time, last_login_ip, last_login_ip_address, total_integral, current_integral, status
</sql>
<!-- 前台用户登录接口 -->
<select id="login" resultType="cn.bunny.vo.system.LoginVo">
select
<include refid="Base_Column_List"/>
from user
where (email = #{username} and password = #{password})
or (nick_name = #{username} and password = #{password})
</select>
</mapper>

View File

@ -0,0 +1,21 @@
<?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="cn.bunny.service.web.mapper.UserRoleMapper">
<!-- 通用查询映射结果 -->
<resultMap id="BaseResultMap" type="cn.bunny.entity.system.UserRole">
<id column="id" property="id"/>
<result column="user_id" property="userId"/>
<result column="role_name" property="roleName"/>
<result column="description" property="description"/>
<result column="role_code" property="roleCode"/>
<result column="create_time" property="createTime"/>
<result column="update_time" property="updateTime"/>
</resultMap>
<!-- 通用查询结果列 -->
<sql id="Base_Column_List">
id, user_id, role_name, description, role_code, create_time, update_time
</sql>
</mapper>