项目搭建
创建seckill秒杀系统项目
导入依赖
在创建Spring boot项目时勾选以下依赖:
- Spring Web
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
- Thymeleaf
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
- MySQL
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
- MyBatis Plus
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.4.0</version>
</dependency>
- Lombok
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
配置组件的属性
创建application.yml
spring:
thymeleaf:
cache: false # 关闭缓存
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/seckill?useUnicode=true&characterEncoding=utf8&serverTimezone=GMT
username: root
password: "0000" # 0开头的密码要加双引号
hikari:
pool-name: DataHikariCP # 连接池名
minimum-idle: 5 # 最小空闲连接数
idle-timeout: 1800000 # 空闲连接最大存活时间
maximum-pool-size: 10 # 最大连接数
auto-commit: true # 从连接池返回的连接自动提交
max-lifetime: 1800000 # 连接最大存活时间 0表示永久
connection-timeout: 30000 # 连接超时时间
connection-test-query: SELECT 1 # 测试连接是否可用的查询语句
mybatis-plus:
mapper-locations: classpath*:/mapper/*Mapper.xml # Mapper.xml映射文件
type-aliases-package: com.tracyqaq.pojo # 别名类的路径
logging:
level:
com.tracyqaq.mapper: debug
在启动类上添加mapper包的扫描地址
启动类SeckillDemoApplication.java
@SpringBootApplication
@MapperScan("com.tracyqaq.mapper")
public class SeckillDemoApplication {
public static void main(String[] args) {
SpringApplication.run(SeckillDemoApplication.class, args);
}
}
建立数据库
建立数据库seckill,建立用户表t_user,其中用户的ID用手机号表示,password为两次盐值加密后的密码。
CREATE TABLE IF NOT EXISTS t_user(
`id` BIGINT(20) NOT NULL COMMENT '用户ID:手机号',
`nickname` VARCHAR(255) NOT NULL,
`password` VARCHAR(32) DEFAULT NULL COMMENT 'MD5(MD5(password明文+固定salt)+salt)',
`salt` VARCHAR(10) DEFAULT NULL,
`head` VARCHAR(128) DEFAULT NULL COMMENT '头像',
`register_date` DATETIME DEFAULT NULL COMMENT '注册时间',
`last_login_date` DATETIME DEFAULT NULL COMMENT '最后一次登录时间',
`login_count` INT(11) DEFAULT '0' COMMENT '登录次数',
PRIMARY KEY(`id``t_user`)
)
盐值加密(MD5)
防止用户输入的明文密码在网络传输过程中被窃取,因此设置盐值加密,定义salt变量,通过加密规则对明文密码加密。第一次加密为:从用户端(前端)到后端,盐值设置为1a2b3c4d,加密规则为空字符串+盐值的第0位+第2位+明文密码+第五位+第四位。第二次加密为:从后端到数据库,盐值可从数据库表中字段调用,加密规则暂定与第一次相同。
在utils包下创建MD5util.java
@Component
public class MD5util {
public static String md5(String src) {
return DigestUtils.md5Hex(src);
}
// 第一次使用的盐
private static final String salt = "1a2b3c4d";
// 第一次加密 用户端到后端
public static String inputPassToBack(String inputPass) {
// 12passwordc3
String str = "" + salt.charAt(0) + salt.charAt(2) + inputPass + salt.charAt(5) + salt.charAt(4);
return md5(str);
}
// 第二次加密 后端到数据库 String salt与数据库字段对其
public static String backToDB(String Pass, String salt) {
String str = "" + salt.charAt(0) + salt.charAt(2) + Pass + salt.charAt(5) + salt.charAt(4);
return md5(str);
}
// 封装两次加密
public static String inputPassToDB(String inputPass, String salt) {
String backPass = inputPassToBack(inputPass);
String dbPass = backToDB(backPass, salt);
return dbPass;
}
public static void main(String[] args) {
System.out.println(inputPassToBack("123456"));
System.out.println(backToDB("d3b1294a61a07da9b49b6e22b2cbd7f9", "1a2b3c4d"));
System.out.println(inputPassToDB("123456", "1a2b3c4d"));
}
}
测试:用户明文密码为123456,第一次加密后结果为d3b1294a61a07da9b49b6e22b2cbd7f9,第二次加密结果为b7797cce01b4b131b433b6acf4add449。将两次加密过程封装后得到第二次加密结果依然为b7797cce01b4b131b433b6acf4add449。
逆向工程
利用Mybatis Plus generator,根据数据库表信息,搭建项目的业务逻辑框架。
创建新Spring boot项目generator
导入依赖
- Mybatis Plus generator
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-generator</artifactId>
<version>3.4.0</version>
</dependency>
- Freemarker
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
<version>2.3.30</version>
</dependency>
逆向工程工具类
CodeGenerator.java
public class CodeGenerator {
public static String scanner(String tip) {
Scanner scanner = new Scanner(System.in);
StringBuilder help = new StringBuilder();
help.append("请输入" + tip + ":");
System.out.println(help.toString());
if (scanner.hasNext()) {
String ipt = scanner.next();
if (StringUtils.isNotBlank(ipt)) {
return ipt;
}
}
throw new MybatisPlusException("请输入正确的" + tip + "!");
}
public static void main(String[] args) {
// 代码生成器
AutoGenerator mpg = new AutoGenerator();
// 全局配置
GlobalConfig gc = new GlobalConfig();
String projectPath = System.getProperty("user.dir");
gc.setOutputDir(projectPath + "/src/main/java");
gc.setAuthor("TracyQAQ"); // 作者
gc.setOpen(false); // 打开输出目录
gc.setBaseResultMap(true);
gc.setBaseColumnList(true);
gc.setDateType(DateType.ONLY_DATE); // 日期格式
// gc.setSwagger2(true); 实体属性 Swagger2 注解
mpg.setGlobalConfig(gc);
// 数据源配置
DataSourceConfig dsc = new DataSourceConfig();
dsc.setUrl("jdbc:mysql://localhost:3306/seckill?useUnicode=true&characterEncoding=utf8&serverTimezone=GMT");
// dsc.setSchemaName("public");
dsc.setDriverName("com.mysql.cj.jdbc.Driver");
dsc.setUsername("root");
dsc.setPassword("0000");
mpg.setDataSource(dsc);
// 包配置
PackageConfig pc = new PackageConfig();
pc.setParent("com.tracyqaq")
.setEntity("pojo")
.setMapper("mapper")
.setService("service")
.setServiceImpl("service.impl")
.setController("controller");
mpg.setPackageInfo(pc);
// 自定义配置
InjectionConfig cfg = new InjectionConfig() {
@Override
public void initMap() {
// to do nothing
}
};
// 如果模板引擎是 freemarker
String templatePath = "/templates/mapper.xml.ftl";
// 如果模板引擎是 velocity
// String templatePath = "/templates/mapper.xml.vm";
// 自定义输出配置
List<FileOutConfig> focList = new ArrayList<>();
// 自定义配置会被优先输出
focList.add(new FileOutConfig(templatePath) {
@Override
public String outputFile(TableInfo tableInfo) {
// 自定义输出文件名 , 如果你 Entity 设置了前后缀、此处注意 xml 的名称会跟着发生变化!!
return projectPath + "/src/main/resources/mapper/" + pc.getModuleName()
+ "/" + tableInfo.getEntityName() + "Mapper" + StringPool.DOT_XML;
}
});
cfg.setFileOutConfigList(focList);
mpg.setCfg(cfg);
// 配置模板
TemplateConfig templateConfig = new TemplateConfig()
.setEntity("templates/entity2.java")
.setMapper("templates/mapper2.java")
.setService("templates/service2.java")
.setServiceImpl("templates/serviceImpl2.java")
.setController("templates/controller2.java");
templateConfig.setXml(null);
mpg.setTemplate(templateConfig);
// 策略配置
StrategyConfig strategy = new StrategyConfig();
strategy.setNaming(NamingStrategy.underline_to_camel); // 数据库表映射到实体的命名策略
strategy.setColumnNaming(NamingStrategy.underline_to_camel); // 数据库表字段映射到实体的命名策略
strategy.setEntityLombokModel(true);
strategy.setInclude(scanner("表名,多个英文逗号分割").split(","));
strategy.setControllerMappingHyphenStyle(true);
strategy.setTablePrefix("t_");
mpg.setStrategy(strategy);
mpg.setTemplateEngine(new FreemarkerTemplateEngine());
mpg.execute();
}
}
将mybatis-plus-generator包下的ftl文件复制到resources-templates下,每个名字后面加2。
运行后输入表名,自动生成以下目录及文件:
将生成的目录文件及mapper包下的UserMapper.xml复制到原seckill项目中,项目框架搭建完毕。