feat(修改): 🚀 不推送logs文件
This commit is contained in:
parent
d621865528
commit
17ddb8750e
|
@ -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
|
|
|
@ -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>
|
|
@ -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();
|
||||||
|
}
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -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 = "密码不能为空";
|
||||||
|
}
|
|
@ -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 = "验证码失效或不存在";
|
||||||
|
}
|
|
@ -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";
|
||||||
|
}
|
|
@ -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 = "发送消息不能为空";
|
||||||
|
}
|
|
@ -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 = "上传文件失败";
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
|
@ -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::";
|
||||||
|
}
|
|
@ -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";
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
|
@ -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";
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
|
@ -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; // 图片验证码对应的字符串数据
|
||||||
|
}
|
|
@ -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>
|
|
@ -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();
|
||||||
|
}
|
||||||
|
}
|
|
@ -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) {
|
||||||
|
}
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -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的登录只能是表单形式 并且用户名密码需要时username、password,可以通过继承 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));
|
||||||
|
}
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -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));
|
||||||
|
}
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -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));
|
||||||
|
}
|
||||||
|
}
|
|
@ -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> {
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
|
@ -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("定时任务执行...");
|
||||||
|
}
|
||||||
|
}
|
|
@ -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
|
|
@ -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>
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -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"
|
|
@ -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万
|
|
@ -0,0 +1,16 @@
|
||||||
|
-----------------▄██-█▄---------
|
||||||
|
-----------------███▄██▄--------
|
||||||
|
-----------------███████--------
|
||||||
|
-----------------▀███████-------
|
||||||
|
-------------------██████▄▄-----
|
||||||
|
-------------------█████████▄---
|
||||||
|
-------------------██████▄████--
|
||||||
|
-------▄███████████████████████-
|
||||||
|
-----▄███████████████████████▀--
|
||||||
|
---▄██████████████████████------
|
||||||
|
---███████████████████████------
|
||||||
|
---███████████████████████------
|
||||||
|
-▄▄██████████████████████▀------
|
||||||
|
-█████████████████▀█████--------
|
||||||
|
-▀██████████████▀▀-▀█████▄------
|
||||||
|
-------▀▀▀▀▀▀▀▀▀------▀▀▀▀------
|
Binary file not shown.
After Width: | Height: | Size: 17 KiB |
|
@ -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>
|
|
@ -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
|
|
@ -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>
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -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();
|
||||||
|
}
|
|
@ -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("开始进行自动填充");
|
||||||
|
}
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -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 {
|
||||||
|
|
||||||
|
}
|
|
@ -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 {
|
||||||
|
|
||||||
|
}
|
|
@ -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 {
|
||||||
|
|
||||||
|
}
|
|
@ -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> {
|
||||||
|
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
|
@ -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> {
|
||||||
|
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -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();
|
||||||
|
}
|
|
@ -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> {
|
||||||
|
|
||||||
|
}
|
|
@ -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> {
|
||||||
|
|
||||||
|
}
|
|
@ -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> {
|
||||||
|
|
||||||
|
}
|
|
@ -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();
|
||||||
|
}
|
||||||
|
}
|
|
@ -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 {
|
||||||
|
|
||||||
|
}
|
|
@ -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 {
|
||||||
|
|
||||||
|
}
|
|
@ -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 {
|
||||||
|
|
||||||
|
}
|
|
@ -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
|
|
@ -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万
|
|
@ -0,0 +1,16 @@
|
||||||
|
-----------------▄██-█▄---------
|
||||||
|
-----------------███▄██▄--------
|
||||||
|
-----------------███████--------
|
||||||
|
-----------------▀███████-------
|
||||||
|
-------------------██████▄▄-----
|
||||||
|
-------------------█████████▄---
|
||||||
|
-------------------██████▄████--
|
||||||
|
-------▄███████████████████████-
|
||||||
|
-----▄███████████████████████▀--
|
||||||
|
---▄██████████████████████------
|
||||||
|
---███████████████████████------
|
||||||
|
---███████████████████████------
|
||||||
|
-▄▄██████████████████████▀------
|
||||||
|
-█████████████████▀█████--------
|
||||||
|
-▀██████████████▀▀-▀█████▄------
|
||||||
|
-------▀▀▀▀▀▀▀▀▀------▀▀▀▀------
|
Binary file not shown.
After Width: | Height: | Size: 17 KiB |
|
@ -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>
|
|
@ -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>
|
|
@ -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>
|
|
@ -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>
|
Loading…
Reference in New Issue