7103 字
约 23 分钟
40
appendix_B
2026-09-26
无标签
附录B 验证码模块源码详解
模块概览(面向 0 基础读者):
- 提供图形/短信验证码生成、存储与校验接口。
- 整合 Kaptcha、Redis 实现验证码服务的生成与分发。
- 支持图形验证码、数字验证码等多种策略可插拔。
核心目录:
xuecheng-plus-checkcode/pom.xmlxuecheng-plus-checkcode/src/main/java/com/xuecheng/checkcode/configxuecheng-plus-checkcode/src/main/java/com/xuecheng/checkcode/controllerxuecheng-plus-checkcode/src/main/java/com/xuecheng/checkcode/modelxuecheng-plus-checkcode/src/main/java/com/xuecheng/checkcode/service
文件:xuecheng-plus-checkcode/pom.xml
<?xml version="1.0" encoding="UTF-8"?> <!-- XML 声明 -->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" <!-- SQL 语句片段 -->
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <!-- SQL 语句片段 -->
<modelVersion>4.0.0</modelVersion> <!-- SQL 语句片段 -->
<parent> <!-- SQL 语句片段 -->
<artifactId>xuecheng-plus-parent</artifactId> <!-- SQL 语句片段 -->
<groupId>com.xuecheng</groupId> <!-- SQL 语句片段 -->
<version>0.0.1-SNAPSHOT</version> <!-- SQL 语句片段 -->
<relativePath>../xuecheng-plus-parent</relativePath> <!-- SQL 语句片段 -->
</parent> <!-- SQL 语句片段 -->
<artifactId>xuecheng-plus-checkcode</artifactId> <!-- SQL 语句片段 -->
<dependencies> <!-- SQL 语句片段 -->
<dependency> <!-- SQL 语句片段 -->
<groupId>com.xuecheng</groupId> <!-- SQL 语句片段 -->
<artifactId>xuecheng-plus-base</artifactId> <!-- SQL 语句片段 -->
<version>0.0.1-SNAPSHOT</version> <!-- SQL 语句片段 -->
</dependency> <!-- SQL 语句片段 -->
<dependency> <!-- SQL 语句片段 -->
<groupId>com.alibaba.cloud</groupId> <!-- SQL 语句片段 -->
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> <!-- SQL 语句片段 -->
</dependency> <!-- SQL 语句片段 -->
<dependency> <!-- SQL 语句片段 -->
<groupId>com.alibaba.cloud</groupId> <!-- SQL 语句片段 -->
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId> <!-- SQL 语句片段 -->
</dependency> <!-- SQL 语句片段 -->
<dependency> <!-- SQL 语句片段 -->
<groupId>com.github.penggle</groupId> <!-- SQL 语句片段 -->
<artifactId>kaptcha</artifactId> <!-- SQL 语句片段 -->
<version>2.3.2</version> <!-- SQL 语句片段 -->
</dependency> <!-- SQL 语句片段 -->
<!-- Spring Boot 的 Spring Web MVC 集成 -->
<dependency> <!-- SQL 语句片段 -->
<groupId>org.springframework.boot</groupId> <!-- SQL 语句片段 -->
<artifactId>spring-boot-starter-web</artifactId> <!-- SQL 语句片段 -->
</dependency> <!-- SQL 语句片段 -->
<dependency> <!-- SQL 语句片段 -->
<groupId>org.springframework.boot</groupId> <!-- SQL 语句片段 -->
<artifactId>spring-boot-starter-validation</artifactId> <!-- SQL 语句片段 -->
</dependency> <!-- SQL 语句片段 -->
<!-- 排除 Spring Boot 依赖的日志包冲突 -->
<dependency> <!-- SQL 语句片段 -->
<groupId>org.springframework.boot</groupId> <!-- SQL 语句片段 -->
<artifactId>spring-boot-starter</artifactId> <!-- SQL 语句片段 -->
<exclusions> <!-- SQL 语句片段 -->
<exclusion> <!-- SQL 语句片段 -->
<groupId>org.springframework.boot</groupId> <!-- SQL 语句片段 -->
<artifactId>spring-boot-starter-logging</artifactId> <!-- SQL 语句片段 -->
</exclusion> <!-- SQL 语句片段 -->
</exclusions> <!-- SQL 语句片段 -->
</dependency> <!-- SQL 语句片段 -->
<dependency> <!-- SQL 语句片段 -->
<groupId>org.springframework.boot</groupId> <!-- SQL 语句片段 -->
<artifactId>spring-boot-starter-data-redis</artifactId> <!-- SQL 语句片段 -->
</dependency> <!-- SQL 语句片段 -->
<dependency> <!-- SQL 语句片段 -->
<groupId>org.apache.commons</groupId> <!-- SQL 语句片段 -->
<artifactId>commons-pool2</artifactId> <!-- SQL 语句片段 -->
<version>2.6.2</version> <!-- SQL 语句片段 -->
</dependency> <!-- SQL 语句片段 -->
<!-- Spring Boot 集成 Junit -->
<dependency> <!-- SQL 语句片段 -->
<groupId>org.springframework.boot</groupId> <!-- SQL 语句片段 -->
<artifactId>spring-boot-starter-test</artifactId> <!-- SQL 语句片段 -->
<scope>test</scope> <!-- SQL 语句片段 -->
</dependency> <!-- SQL 语句片段 -->
<!-- Spring Boot 集成 log4j2 -->
<dependency> <!-- SQL 语句片段 -->
<groupId>org.springframework.boot</groupId> <!-- SQL 语句片段 -->
<artifactId>spring-boot-starter-log4j2</artifactId> <!-- SQL 语句片段 -->
</dependency> <!-- SQL 语句片段 -->
<!-- Spring Boot 集成 swagger -->
<dependency> <!-- SQL 语句片段 -->
<groupId>com.spring4all</groupId> <!-- SQL 语句片段 -->
<artifactId>swagger-spring-boot-starter</artifactId> <!-- SQL 语句片段 -->
</dependency> <!-- SQL 语句片段 -->
<dependency> <!-- SQL 语句片段 -->
<groupId>org.projectlombok</groupId> <!-- SQL 语句片段 -->
<artifactId>lombok</artifactId> <!-- SQL 语句片段 -->
</dependency> <!-- SQL 语句片段 -->
</dependencies> <!-- SQL 语句片段 -->
<build> <!-- SQL 语句片段 -->
<finalName>${project.artifactId}-${project.version}</finalName> <!-- SQL 语句片段 -->
<plugins> <!-- SQL 语句片段 -->
<plugin> <!-- SQL 语句片段 -->
<groupId>org.springframework.boot</groupId> <!-- SQL 语句片段 -->
<artifactId>spring-boot-maven-plugin</artifactId> <!-- SQL 语句片段 -->
<version>${spring-boot.version}</version> <!-- SQL 语句片段 -->
<executions> <!-- SQL 语句片段 -->
<execution> <!-- SQL 语句片段 -->
<goals> <!-- SQL 语句片段 -->
<goal>repackage</goal> <!-- SQL 语句片段 -->
</goals> <!-- SQL 语句片段 -->
</execution> <!-- SQL 语句片段 -->
</executions> <!-- SQL 语句片段 -->
</plugin> <!-- SQL 语句片段 -->
<plugin> <!-- SQL 语句片段 -->
<groupId>com.spotify</groupId> <!-- SQL 语句片段 -->
<artifactId>docker-maven-plugin</artifactId> <!-- SQL 语句片段 -->
<version>1.2.2</version> <!-- SQL 语句片段 -->
<configuration> <!-- SQL 语句片段 -->
<!--修改imageName节点的内容,改为私有仓库地址和端口,再加上镜像id和 TAG,我们要直接传到私服-->
<!--配置最后生成的镜像名,docker images里的,我们这边取项目名:版本-->
<!--<imageName>${project.artifactId}:${project.version}</imageName>-->
<imageName>192.168.101.65:5000/${project.artifactId}:${project.version}</imageName> <!-- SQL 语句片段 -->
<!--也可以通过以下方式定义image的tag信息。 -->
<!-- <imageTags>
<imageTag>${project.version}</imageTag> <!-- SQL 语句片段 -->
<!–build 时强制覆盖 tag,配合 imageTags 使用–> <!-- SQL 语句片段 -->
<forceTags>true</forceTags> <!-- SQL 语句片段 -->
<!–build 完成后,push 指定 tag 的镜像,配合 imageTags 使用–> <!-- SQL 语句片段 -->
<pushImageTag>true</pushImageTag> <!-- SQL 语句片段 -->
</imageTags>--> <!-- SQL 语句片段 -->
<baseImage>java:8u20</baseImage> <!-- SQL 语句片段 -->
<maintainer>docker_maven [email protected]</maintainer> <!-- SQL 语句片段 -->
<workdir>/root</workdir> <!-- SQL 语句片段 -->
<cmd>["java", "-version"]</cmd> <!-- SQL 语句片段 -->
<!--来指明Dockerfile文件的所在目录,如果配置了dockerDirectory则忽略baseImage,maintainer等配置-->
<!--<dockerDirectory>./</dockerDirectory>-->
<!--2375是docker的远程端口,插件生成镜像时连接docker,这里需要指定docker远程端口-->
<dockerHost>http://192.168.101.65:2375</dockerHost> <!-- SQL 语句片段 -->
<!--入口点,project.build.finalName就是project标签下的build标签下 的filename标签内容,testDocker-->
<!--相当于启动容器后,会自动执行java -jar ...-->
<entryPoint>["java", "-Dfile.encoding=utf-8","-jar", "/root/${project.build.finalName}.jar"]</entryPoint> <!-- SQL 语句片段 -->
<!--是否推送到docker私有仓库,旧版本插件要配置maven的settings文件。 -->
<pushImage>true</pushImage> <!-- SQL 语句片段 -->
<registryUrl>192.168.101.65:5000</registryUrl> <!-- 这里是复制 jar 包到 docker 容器指定目录配置 --> <!-- SQL 语句片段 -->
<resources> <!-- SQL 语句片段 -->
<resource> <!-- SQL 语句片段 -->
<targetPath>/root</targetPath> <!-- SQL 语句片段 -->
<directory>${project.build.directory}</directory> <!-- SQL 语句片段 -->
<!--把哪个文件上传到docker,相当于Dockerfile里的add app.jar /-->
<include>${project.build.finalName}.jar</include> <!-- 引用公共 SQL 片段 -->
</resource> <!-- SQL 语句片段 -->
</resources> <!-- SQL 语句片段 -->
</configuration> <!-- SQL 语句片段 -->
</plugin> <!-- SQL 语句片段 -->
</plugins> <!-- SQL 语句片段 -->
</build> <!-- SQL 语句片段 -->
</project> <!-- SQL 语句片段 -->
文件:xuecheng-plus-checkcode/src/main/java/com/xuecheng/checkcode/CheckcodeApplication.java
package com.xuecheng.checkcode; // 声明类所在的包路径
import org.springframework.boot.SpringApplication; // 导入 SpringApplication 类
import org.springframework.boot.autoconfigure.SpringBootApplication; // 导入 SpringBootApplication 类
@SpringBootApplication // 使用注解 @SpringBootApplication
public class CheckcodeApplication { // 定义 class CheckcodeApplication
public static void main(String[] args) { // 定义方法 main(...)
SpringApplication.run(CheckcodeApplication.class, args); // 执行语句
} // 代码块结束
} // 代码块结束
文件:xuecheng-plus-checkcode/src/main/java/com/xuecheng/checkcode/config/KaptchaConfig.java
package com.xuecheng.checkcode.config; // 声明类所在的包路径
import com.google.code.kaptcha.impl.DefaultKaptcha; // 导入 DefaultKaptcha 类
import com.google.code.kaptcha.util.Config; // 导入 Config 类
import org.springframework.context.annotation.Bean; // 导入 Bean 类
import org.springframework.context.annotation.Configuration; // 导入 Configuration 类
import java.util.Properties; // 导入 Properties 类
/** // 保留原作者写的块注释
* Kaptcha图片验证码配置类 // 保留原作者写的块注释
* @author 攀博课堂(www.pbteach.com) // 保留原作者写的块注释
* @version 1.0 // 保留原作者写的块注释
**/ // 保留原作者写的块注释
@Configuration // 使用注解 @Configuration
public class KaptchaConfig { // 定义 class KaptchaConfig
//图片验证码生成器,使用开源的kaptcha // 保留原作者写的行内注释
@Bean // 使用注解 @Bean
public DefaultKaptcha producer() { // 定义方法 producer(...)
Properties properties = new Properties(); // 创建 Properties 对象并赋值给 properties
properties.put("kaptcha.border", "no"); // 执行语句
properties.put("kaptcha.textproducer.font.color", "black"); // 执行语句
properties.put("kaptcha.textproducer.char.space", "10"); // 执行语句
properties.put("kaptcha.textproducer.char.length","4"); // 执行语句
properties.put("kaptcha.image.height","34"); // 执行语句
properties.put("kaptcha.image.width","138"); // 执行语句
properties.put("kaptcha.textproducer.font.size","25"); // 执行语句
properties.put("kaptcha.noise.impl","com.google.code.kaptcha.impl.NoNoise"); // 执行语句
Config config = new Config(properties); // 创建 Config 对象并赋值给 config
DefaultKaptcha defaultKaptcha = new DefaultKaptcha(); // 创建 DefaultKaptcha 对象并赋值给 defaultKaptcha
defaultKaptcha.setConfig(config); // 执行语句
return defaultKaptcha; // 返回 defaultKaptcha
} // 代码块结束
} // 代码块结束
文件:xuecheng-plus-checkcode/src/main/java/com/xuecheng/checkcode/controller/CheckCodeController.java
package com.xuecheng.checkcode.controller; // 声明类所在的包路径
import com.xuecheng.base.model.RestResponse; // 导入 RestResponse 类
import com.xuecheng.checkcode.model.CheckCodeParamsDto; // 导入 CheckCodeParamsDto 类
import com.xuecheng.checkcode.model.CheckCodeResultDto; // 导入 CheckCodeResultDto 类
import com.xuecheng.checkcode.service.CheckCodeService; // 导入 CheckCodeService 类
import io.swagger.annotations.Api; // 导入 Api 类
import io.swagger.annotations.ApiImplicitParam; // 导入 ApiImplicitParam 类
import io.swagger.annotations.ApiImplicitParams; // 导入 ApiImplicitParams 类
import io.swagger.annotations.ApiOperation; // 导入 ApiOperation 类
import org.springframework.beans.factory.annotation.Autowired; // 导入 Autowired 类
import org.springframework.web.bind.annotation.*; // 导入 * 类
import javax.annotation.Resource; // 导入 Resource 类
import java.util.Map; // 导入 Map 类
/** // 保留原作者写的块注释
* @author Mr.M // 保留原作者写的块注释
* @version 1.0 // 保留原作者写的块注释
* @description 验证码服务接口 // 保留原作者写的块注释
* @date 2022/9/29 18:39 // 保留原作者写的块注释
*/ // 保留原作者写的块注释
@Api(value = "验证码服务接口") // 使用注解 @Api(value = "验证码服务接口")
@RestController // 使用注解 @RestController
public class CheckCodeController { // 定义 class CheckCodeController
@Resource(name = "PicCheckCodeService") // 使用注解 @Resource(name = "PicCheckCodeService")
private CheckCodeService picCheckCodeService; // 执行语句
@ApiOperation(value="生成验证信息", notes="生成验证信息") // 使用注解 @ApiOperation(value="生成验证信息", notes="生成验证信息")
@PostMapping(value = "/pic") // 使用注解 @PostMapping(value = "/pic")
public CheckCodeResultDto generatePicCheckCode(CheckCodeParamsDto checkCodeParamsDto){ // 定义方法 generatePicCheckCode(...)
return picCheckCodeService.generate(checkCodeParamsDto); // 返回 picCheckCodeService.generate(checkCodeParamsDto)
} // 代码块结束
@ApiOperation(value="校验", notes="校验") // 使用注解 @ApiOperation(value="校验", notes="校验")
@ApiImplicitParams({ // 使用注解 @ApiImplicitParams({
@ApiImplicitParam(name = "name", value = "业务名称", required = true, dataType = "String", paramType="query"), // 使用注解 @ApiImplicitParam(name = "name", value = "业务名称", required = true, dataType = "String", paramType="query"),
@ApiImplicitParam(name = "key", value = "验证key", required = true, dataType = "String", paramType="query"), // 使用注解 @ApiImplicitParam(name = "key", value = "验证key", required = true, dataType = "String", paramType="query"),
@ApiImplicitParam(name = "code", value = "验证码", required = true, dataType = "String", paramType="query") // 使用注解 @ApiImplicitParam(name = "code", value = "验证码", required = true, dataType = "String", paramType="query")
}) // 代码逻辑
@PostMapping(value = "/verify") // 使用注解 @PostMapping(value = "/verify")
public Boolean verify(String key, String code){ // 定义方法 verify(...)
Boolean isSuccess = picCheckCodeService.verify(key,code); // 把 picCheckCodeService.verify(key,code) 赋值给 isSuccess
return isSuccess; // 返回 isSuccess
} // 代码块结束
} // 代码块结束
文件:xuecheng-plus-checkcode/src/main/java/com/xuecheng/checkcode/model/CheckCodeParamsDto.java
package com.xuecheng.checkcode.model; // 声明类所在的包路径
import lombok.Data; // 导入 Data 类
import java.util.Map; // 导入 Map 类
/** // 保留原作者写的块注释
* @author Mr.M // 保留原作者写的块注释
* @version 1.0 // 保留原作者写的块注释
* @description 验证码生成参数类 // 保留原作者写的块注释
* @date 2022/9/29 15:48 // 保留原作者写的块注释
*/ // 保留原作者写的块注释
@Data // 使用注解 @Data
public class CheckCodeParamsDto { // 定义 class CheckCodeParamsDto
/** // 保留原作者写的块注释
* 验证码类型:pic、sms、email等 // 保留原作者写的块注释
*/ // 保留原作者写的块注释
private String checkCodeType; // 执行语句
/** // 保留原作者写的块注释
* 业务携带参数 // 保留原作者写的块注释
*/ // 保留原作者写的块注释
private String param1; // 执行语句
private String param2; // 执行语句
private String param3; // 执行语句
} // 代码块结束
文件:xuecheng-plus-checkcode/src/main/java/com/xuecheng/checkcode/model/CheckCodeResultDto.java
package com.xuecheng.checkcode.model; // 声明类所在的包路径
import lombok.Data; // 导入 Data 类
/** // 保留原作者写的块注释
* @author Mr.M // 保留原作者写的块注释
* @version 1.0 // 保留原作者写的块注释
* @description 验证码生成结果类 // 保留原作者写的块注释
* @date 2022/9/29 15:48 // 保留原作者写的块注释
*/ // 保留原作者写的块注释
@Data // 使用注解 @Data
public class CheckCodeResultDto { // 定义 class CheckCodeResultDto
/** // 保留原作者写的块注释
* key用于验证 // 保留原作者写的块注释
*/ // 保留原作者写的块注释
private String key; // 执行语句
/** // 保留原作者写的块注释
* 混淆后的内容 // 保留原作者写的块注释
* 举例: // 保留原作者写的块注释
* 1.图片验证码为:图片base64编码 // 保留原作者写的块注释
* 2.短信验证码为:null // 保留原作者写的块注释
* 3.邮件验证码为: null // 保留原作者写的块注释
* 4.邮件链接点击验证为:null // 保留原作者写的块注释
* ... // 保留原作者写的块注释
*/ // 保留原作者写的块注释
private String aliasing; // 执行语句
} // 代码块结束
文件:xuecheng-plus-checkcode/src/main/java/com/xuecheng/checkcode/service/AbstractCheckCodeService.java
package com.xuecheng.checkcode.service; // 声明类所在的包路径
import com.xuecheng.checkcode.model.CheckCodeParamsDto; // 导入 CheckCodeParamsDto 类
import com.xuecheng.checkcode.model.CheckCodeResultDto; // 导入 CheckCodeResultDto 类
import lombok.Data; // 导入 Data 类
import lombok.extern.slf4j.Slf4j; // 导入 Slf4j 类
import org.apache.commons.lang.StringUtils; // 导入 StringUtils 类
/** // 保留原作者写的块注释
* @author Mr.M // 保留原作者写的块注释
* @version 1.0 // 保留原作者写的块注释
* @description 验证码接口 // 保留原作者写的块注释
* @date 2022/9/29 15:59 // 保留原作者写的块注释
*/ // 保留原作者写的块注释
@Slf4j // 使用注解 @Slf4j
public abstract class AbstractCheckCodeService implements CheckCodeService { // 代码逻辑
protected CheckCodeGenerator checkCodeGenerator; // 执行语句
protected KeyGenerator keyGenerator; // 执行语句
protected CheckCodeStore checkCodeStore; // 执行语句
public abstract void setCheckCodeGenerator(CheckCodeGenerator checkCodeGenerator); // 执行语句
public abstract void setKeyGenerator(KeyGenerator keyGenerator); // 执行语句
public abstract void setCheckCodeStore(CheckCodeStore CheckCodeStore); // 执行语句
/** // 保留原作者写的块注释
* @description 生成验证公用方法 // 保留原作者写的块注释
* @param checkCodeParamsDto 生成验证码参数 // 保留原作者写的块注释
* @param code_length 验证码长度 // 保留原作者写的块注释
* @param keyPrefix key的前缀 // 保留原作者写的块注释
* @param expire 过期时间 // 保留原作者写的块注释
* @return com.xuecheng.checkcode.service.AbstractCheckCodeService.GenerateResult 生成结果 // 保留原作者写的块注释
* @author Mr.M // 保留原作者写的块注释
* @date 2022/9/30 6:07 // 保留原作者写的块注释
*/ // 保留原作者写的块注释
public GenerateResult generate(CheckCodeParamsDto checkCodeParamsDto,Integer code_length,String keyPrefix,Integer expire){ // 定义方法 generate(...)
//生成四位验证码 // 保留原作者写的行内注释
String code = checkCodeGenerator.generate(code_length); // 把 checkCodeGenerator.generate(code_length) 赋值给 code
log.debug("生成验证码:{}",code); // 执行语句
//生成一个key // 保留原作者写的行内注释
String key = keyGenerator.generate(keyPrefix); // 把 keyGenerator.generate(keyPrefix) 赋值给 key
//存储验证码 // 保留原作者写的行内注释
checkCodeStore.set(key,code,expire); // 执行语句
//返回验证码生成结果 // 保留原作者写的行内注释
GenerateResult generateResult = new GenerateResult(); // 创建 GenerateResult 对象并赋值给 generateResult
generateResult.setKey(key); // 执行语句
generateResult.setCode(code); // 执行语句
return generateResult; // 返回 generateResult
} // 代码块结束
@Data // 使用注解 @Data
protected class GenerateResult{ // 定义 class GenerateResult{
String key; // 执行语句
String code; // 执行语句
} // 代码块结束
public abstract CheckCodeResultDto generate(CheckCodeParamsDto checkCodeParamsDto); // 执行语句
public boolean verify(String key, String code){ // 定义方法 verify(...)
if (StringUtils.isBlank(key) || StringUtils.isBlank(code)){ // 定义方法 方法(...)
return false; // 返回 false
} // 代码块结束
String code_l = checkCodeStore.get(key); // 把 checkCodeStore.get(key) 赋值给 code_l
if (code_l == null){ // 定义方法 方法(...)
return false; // 返回 false
} // 代码块结束
boolean result = code_l.equalsIgnoreCase(code); // 把 code_l.equalsIgnoreCase(code) 赋值给 result
if(result){ // 定义方法 方法(...)
//删除验证码 // 保留原作者写的行内注释
checkCodeStore.remove(key); // 执行语句
} // 代码块结束
return result; // 返回 result
} // 代码块结束
} // 代码块结束
文件:xuecheng-plus-checkcode/src/main/java/com/xuecheng/checkcode/service/CheckCodeService.java
package com.xuecheng.checkcode.service; // 声明类所在的包路径
import com.xuecheng.checkcode.model.CheckCodeParamsDto; // 导入 CheckCodeParamsDto 类
import com.xuecheng.checkcode.model.CheckCodeResultDto; // 导入 CheckCodeResultDto 类
import org.springframework.beans.factory.annotation.Autowired; // 导入 Autowired 类
import javax.annotation.Resource; // 导入 Resource 类
import java.util.Map; // 导入 Map 类
/** // 保留原作者写的块注释
* @author Mr.M // 保留原作者写的块注释
* @version 1.0 // 保留原作者写的块注释
* @description 验证码接口 // 保留原作者写的块注释
* @date 2022/9/29 15:59 // 保留原作者写的块注释
*/ // 保留原作者写的块注释
public interface CheckCodeService { // 定义 interface CheckCodeService
/** // 保留原作者写的块注释
* @description 生成验证码 // 保留原作者写的块注释
* @param checkCodeParamsDto 生成验证码参数 // 保留原作者写的块注释
* @return com.xuecheng.checkcode.model.CheckCodeResultDto 验证码结果 // 保留原作者写的块注释
* @author Mr.M // 保留原作者写的块注释
* @date 2022/9/29 18:21 // 保留原作者写的块注释
*/ // 保留原作者写的块注释
CheckCodeResultDto generate(CheckCodeParamsDto checkCodeParamsDto); // 执行语句
/** // 保留原作者写的块注释
* @description 校验验证码 // 保留原作者写的块注释
* @param key // 保留原作者写的块注释
* @param code // 保留原作者写的块注释
* @return boolean // 保留原作者写的块注释
* @author Mr.M // 保留原作者写的块注释
* @date 2022/9/29 18:46 // 保留原作者写的块注释
*/ // 保留原作者写的块注释
public boolean verify(String key, String code); // 执行语句
/** // 保留原作者写的块注释
* @description 验证码生成器 // 保留原作者写的块注释
* @author Mr.M // 保留原作者写的块注释
* @date 2022/9/29 16:34 // 保留原作者写的块注释
*/ // 保留原作者写的块注释
public interface CheckCodeGenerator{ // 定义 interface CheckCodeGenerator{
/** // 保留原作者写的块注释
* 验证码生成 // 保留原作者写的块注释
* @return 验证码 // 保留原作者写的块注释
*/ // 保留原作者写的块注释
String generate(int length); // 执行语句
} // 代码块结束
/** // 保留原作者写的块注释
* @description key生成器 // 保留原作者写的块注释
* @author Mr.M // 保留原作者写的块注释
* @date 2022/9/29 16:34 // 保留原作者写的块注释
*/ // 保留原作者写的块注释
public interface KeyGenerator{ // 定义 interface KeyGenerator{
/** // 保留原作者写的块注释
* key生成 // 保留原作者写的块注释
* @return 验证码 // 保留原作者写的块注释
*/ // 保留原作者写的块注释
String generate(String prefix); // 执行语句
} // 代码块结束
/** // 保留原作者写的块注释
* @description 验证码存储 // 保留原作者写的块注释
* @author Mr.M // 保留原作者写的块注释
* @date 2022/9/29 16:34 // 保留原作者写的块注释
*/ // 保留原作者写的块注释
public interface CheckCodeStore{ // 定义 interface CheckCodeStore{
/** // 保留原作者写的块注释
* @description 向缓存设置key // 保留原作者写的块注释
* @param key key // 保留原作者写的块注释
* @param value value // 保留原作者写的块注释
* @param expire 过期时间,单位秒 // 保留原作者写的块注释
* @return void // 保留原作者写的块注释
* @author Mr.M // 保留原作者写的块注释
* @date 2022/9/29 17:15 // 保留原作者写的块注释
*/ // 保留原作者写的块注释
void set(String key, String value, Integer expire); // 执行语句
String get(String key); // 执行语句
void remove(String key); // 执行语句
} // 代码块结束
} // 代码块结束
文件:xuecheng-plus-checkcode/src/main/java/com/xuecheng/checkcode/service/impl/MemoryCheckCodeStore.java
package com.xuecheng.checkcode.service.impl; // 声明类所在的包路径
import com.xuecheng.checkcode.service.CheckCodeService; // 导入 CheckCodeService 类
import org.springframework.beans.factory.annotation.Autowired; // 导入 Autowired 类
import org.springframework.stereotype.Component; // 导入 Component 类
import java.util.HashMap; // 导入 HashMap 类
import java.util.Map; // 导入 Map 类
/** // 保留原作者写的块注释
* @author Mr.M // 保留原作者写的块注释
* @version 1.0 // 保留原作者写的块注释
* @description 使用本地内存存储验证码,测试用 // 保留原作者写的块注释
* @date 2022/9/29 18:36 // 保留原作者写的块注释
*/ // 保留原作者写的块注释
@Component("MemoryCheckCodeStore") // 使用注解 @Component("MemoryCheckCodeStore")
public class MemoryCheckCodeStore implements CheckCodeService.CheckCodeStore { // 定义 class MemoryCheckCodeStore
Map<String,String> map = new HashMap<String,String>(); // 创建 HashMap<String,String> 对象并赋值给 map
@Override // 使用注解 @Override
public void set(String key, String value, Integer expire) { // 定义方法 set(...)
map.put(key,value); // 执行语句
} // 代码块结束
@Override // 使用注解 @Override
public String get(String key) { // 定义方法 get(...)
return map.get(key); // 返回 map.get(key)
} // 代码块结束
@Override // 使用注解 @Override
public void remove(String key) { // 定义方法 remove(...)
map.remove(key); // 执行语句
} // 代码块结束
} // 代码块结束
文件:xuecheng-plus-checkcode/src/main/java/com/xuecheng/checkcode/service/impl/NumberLetterCheckCodeGenerator.java
package com.xuecheng.checkcode.service.impl; // 声明类所在的包路径
import com.xuecheng.checkcode.model.CheckCodeParamsDto; // 导入 CheckCodeParamsDto 类
import com.xuecheng.checkcode.service.CheckCodeService; // 导入 CheckCodeService 类
import org.springframework.stereotype.Component; // 导入 Component 类
import java.util.Random; // 导入 Random 类
/** // 保留原作者写的块注释
* @author Mr.M // 保留原作者写的块注释
* @version 1.0 // 保留原作者写的块注释
* @description 数字字母生成器 // 保留原作者写的块注释
* @date 2022/9/29 18:28 // 保留原作者写的块注释
*/ // 保留原作者写的块注释
@Component("NumberLetterCheckCodeGenerator") // 使用注解 @Component("NumberLetterCheckCodeGenerator")
public class NumberLetterCheckCodeGenerator implements CheckCodeService.CheckCodeGenerator { // 定义 class NumberLetterCheckCodeGenerator
@Override // 使用注解 @Override
public String generate(int length) { // 定义方法 generate(...)
String str="ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; // 把 "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789" 赋值给 str
Random random=new Random(); // 创建 Random 对象并赋值给 random
StringBuffer sb=new StringBuffer(); // 创建 StringBuffer 对象并赋值给 sb
for(int i=0;i<length;i++){ // 定义方法 方法(...)
int number=random.nextInt(36); // 把 random.nextInt(36) 赋值给 number
sb.append(str.charAt(number)); // 执行语句
} // 代码块结束
return sb.toString(); // 返回 sb.toString()
} // 代码块结束
} // 代码块结束
文件:xuecheng-plus-checkcode/src/main/java/com/xuecheng/checkcode/service/impl/PicCheckCodeServiceImpl.java
package com.xuecheng.checkcode.service.impl; // 声明类所在的包路径
import com.google.code.kaptcha.impl.DefaultKaptcha; // 导入 DefaultKaptcha 类
import com.xuecheng.base.utils.EncryptUtil; // 导入 EncryptUtil 类
import com.xuecheng.checkcode.model.CheckCodeParamsDto; // 导入 CheckCodeParamsDto 类
import com.xuecheng.checkcode.model.CheckCodeResultDto; // 导入 CheckCodeResultDto 类
import com.xuecheng.checkcode.service.AbstractCheckCodeService; // 导入 AbstractCheckCodeService 类
import com.xuecheng.checkcode.service.CheckCodeService; // 导入 CheckCodeService 类
import org.springframework.beans.factory.annotation.Autowired; // 导入 Autowired 类
import org.springframework.stereotype.Service; // 导入 Service 类
import sun.misc.BASE64Encoder; // 导入 BASE64Encoder 类
import javax.annotation.Resource; // 导入 Resource 类
import javax.imageio.ImageIO; // 导入 ImageIO 类
import java.awt.image.BufferedImage; // 导入 BufferedImage 类
import java.io.ByteArrayOutputStream; // 导入 ByteArrayOutputStream 类
import java.io.IOException; // 导入 IOException 类
/** // 保留原作者写的块注释
* @author Mr.M // 保留原作者写的块注释
* @version 1.0 // 保留原作者写的块注释
* @description 图片验证码生成器 // 保留原作者写的块注释
* @date 2022/9/29 16:16 // 保留原作者写的块注释
*/ // 保留原作者写的块注释
@Service("PicCheckCodeService") // 使用注解 @Service("PicCheckCodeService")
public class PicCheckCodeServiceImpl extends AbstractCheckCodeService implements CheckCodeService { // 定义 class PicCheckCodeServiceImpl
@Autowired // 使用注解 @Autowired
private DefaultKaptcha kaptcha; // 执行语句
@Resource(name="NumberLetterCheckCodeGenerator") // 使用注解 @Resource(name="NumberLetterCheckCodeGenerator")
@Override // 使用注解 @Override
public void setCheckCodeGenerator(CheckCodeGenerator checkCodeGenerator) { // 定义方法 setCheckCodeGenerator(...)
this.checkCodeGenerator = checkCodeGenerator; // 把 checkCodeGenerator 赋值给 this.checkCodeGenerator
} // 代码块结束
@Resource(name="UUIDKeyGenerator") // 使用注解 @Resource(name="UUIDKeyGenerator")
@Override // 使用注解 @Override
public void setKeyGenerator(KeyGenerator keyGenerator) { // 定义方法 setKeyGenerator(...)
this.keyGenerator = keyGenerator; // 把 keyGenerator 赋值给 this.keyGenerator
} // 代码块结束
@Resource(name="RedisCheckCodeStore") // 使用注解 @Resource(name="RedisCheckCodeStore")
@Override // 使用注解 @Override
public void setCheckCodeStore(CheckCodeStore checkCodeStore) { // 定义方法 setCheckCodeStore(...)
this.checkCodeStore = checkCodeStore; // 把 checkCodeStore 赋值给 this.checkCodeStore
} // 代码块结束
@Override // 使用注解 @Override
public CheckCodeResultDto generate(CheckCodeParamsDto checkCodeParamsDto) { // 定义方法 generate(...)
GenerateResult generate = generate(checkCodeParamsDto, 4, "checkcode:", 300); // 把 generate(checkCodeParamsDto, 4, "checkcode:", 300) 赋值给 generate
String key = generate.getKey(); // 把 generate.getKey() 的返回值赋给 key
String code = generate.getCode(); // 把 generate.getCode() 的返回值赋给 code
String pic = createPic(code); // 把 createPic(code) 赋值给 pic
CheckCodeResultDto checkCodeResultDto = new CheckCodeResultDto(); // 创建 CheckCodeResultDto 对象并赋值给 checkCodeResultDto
checkCodeResultDto.setAliasing(pic); // 执行语句
checkCodeResultDto.setKey(key); // 执行语句
return checkCodeResultDto; // 返回 checkCodeResultDto
} // 代码块结束
private String createPic(String code) { // 定义方法 createPic(...)
// 生成图片验证码 // 保留原作者写的行内注释
ByteArrayOutputStream outputStream = null; // 把变量 outputStream 初始化为 null
BufferedImage image = kaptcha.createImage(code); // 把 kaptcha.createImage(code) 赋值给 image
outputStream = new ByteArrayOutputStream(); // 创建 ByteArrayOutputStream 对象并赋值给 outputStream
String imgBase64Encoder = null; // 把变量 imgBase64Encoder 初始化为 null
try { // 尝试执行可能抛出异常的代码
// 对字节数组Base64编码 // 保留原作者写的行内注释
BASE64Encoder base64Encoder = new BASE64Encoder(); // 创建 BASE64Encoder 对象并赋值给 base64Encoder
ImageIO.write(image, "png", outputStream); // 执行语句
imgBase64Encoder = "data:image/png;base64," + EncryptUtil.encodeBase64(outputStream.toByteArray()); // 把 "data:image/png;base64," + EncryptUtil.encodeBase64(outputStream.toByteArray()) 赋值给 imgBase64Encoder
} catch (IOException e) { // 定义方法 catch(...)
e.printStackTrace(); // 执行语句
} finally { // 代码逻辑
try { // 尝试执行可能抛出异常的代码
outputStream.close(); // 执行语句
} catch (IOException e) { // 定义方法 catch(...)
e.printStackTrace(); // 执行语句
} // 代码块结束
} // 代码块结束
return imgBase64Encoder; // 返回 imgBase64Encoder
} // 代码块结束
} // 代码块结束
文件:xuecheng-plus-checkcode/src/main/java/com/xuecheng/checkcode/service/impl/RedisCheckCodeStore.java
package com.xuecheng.checkcode.service.impl; // 声明类所在的包路径
import com.xuecheng.checkcode.service.CheckCodeService; // 导入 CheckCodeService 类
import org.springframework.beans.factory.annotation.Autowired; // 导入 Autowired 类
import org.springframework.data.redis.core.RedisTemplate; // 导入 RedisTemplate 类
import org.springframework.stereotype.Component; // 导入 Component 类
import java.util.HashMap; // 导入 HashMap 类
import java.util.Map; // 导入 Map 类
import java.util.concurrent.TimeUnit; // 导入 TimeUnit 类
/** // 保留原作者写的块注释
* @author Mr.M // 保留原作者写的块注释
* @version 1.0 // 保留原作者写的块注释
* @description 使用redis存储验证码,测试用 // 保留原作者写的块注释
* @date 2022/9/29 18:36 // 保留原作者写的块注释
*/ // 保留原作者写的块注释
@Component("RedisCheckCodeStore") // 使用注解 @Component("RedisCheckCodeStore")
public class RedisCheckCodeStore implements CheckCodeService.CheckCodeStore { // 定义 class RedisCheckCodeStore
@Autowired // 使用注解 @Autowired
RedisTemplate redisTemplate; // 执行语句
@Override // 使用注解 @Override
public void set(String key, String value, Integer expire) { // 定义方法 set(...)
redisTemplate.opsForValue().set(key,value,expire, TimeUnit.SECONDS); // 执行语句
} // 代码块结束
@Override // 使用注解 @Override
public String get(String key) { // 定义方法 get(...)
return (String) redisTemplate.opsForValue().get(key); // 返回 (String) redisTemplate.opsForValue().get(key)
} // 代码块结束
@Override // 使用注解 @Override
public void remove(String key) { // 定义方法 remove(...)
redisTemplate.delete(key); // 执行语句
} // 代码块结束
} // 代码块结束
文件:xuecheng-plus-checkcode/src/main/java/com/xuecheng/checkcode/service/impl/UUIDKeyGenerator.java
package com.xuecheng.checkcode.service.impl; // 声明类所在的包路径
import com.xuecheng.checkcode.service.CheckCodeService; // 导入 CheckCodeService 类
import org.springframework.stereotype.Component; // 导入 Component 类
import java.util.UUID; // 导入 UUID 类
/** // 保留原作者写的块注释
* @author Mr.M // 保留原作者写的块注释
* @version 1.0 // 保留原作者写的块注释
* @description uuid生成器 // 保留原作者写的块注释
* @date 2022/9/29 16:16 // 保留原作者写的块注释
*/ // 保留原作者写的块注释
@Component("UUIDKeyGenerator") // 使用注解 @Component("UUIDKeyGenerator")
public class UUIDKeyGenerator implements CheckCodeService.KeyGenerator { // 定义 class UUIDKeyGenerator
@Override // 使用注解 @Override
public String generate(String prefix) { // 定义方法 generate(...)
String uuid = UUID.randomUUID().toString(); // 把 UUID.randomUUID().toString() 的返回值赋给 uuid
return prefix + uuid.replaceAll("-", ""); // 返回 prefix + uuid.replaceAll("-", "")
} // 代码块结束
} // 代码块结束
文件:xuecheng-plus-checkcode/src/main/resources/bootstrap.yml
spring:
application:
name: checkcode
cloud:
nacos:
server-addr: 192.168.101.65:8848
discovery:
namespace: dev402
group: xuecheng-plus-project
config:
namespace: dev402
group: xuecheng-plus-project
file-extension: yaml
refresh-enabled: true
shared-configs:
- data-id: swagger-${spring.profiles.active}.yaml
group: xuecheng-plus-common
refresh: true
- data-id: logging-${spring.profiles.active}.yaml
group: xuecheng-plus-common
refresh: true
- data-id: redis-${spring.profiles.active}.yaml
group: xuecheng-plus-common
refresh: true
profiles:
active: dev
文件:xuecheng-plus-checkcode/src/main/resources/log4j2-dev.xml
<?xml version="1.0" encoding="UTF-8"?> <!-- XML 声明 -->
<Configuration monitorInterval="180" packages=""> <!-- SQL 语句片段 -->
<properties> <!-- SQL 语句片段 -->
<property name="logdir">logs</property> <!-- SQL 语句片段 -->
<property name="PATTERN">%date{YYYY-MM-dd HH:mm:ss,SSS} %level [%thread][%file:%line] - %msg%n%throwable</property> <!-- SQL 语句片段 -->
</properties> <!-- SQL 语句片段 -->
<Appenders> <!-- SQL 语句片段 -->
<Console name="Console" target="SYSTEM_OUT"> <!-- SQL 语句片段 -->
<PatternLayout pattern="${PATTERN}"/> <!-- SQL 语句片段 -->
</Console> <!-- SQL 语句片段 -->
<RollingFile name="ErrorAppender" fileName="${logdir}/error.log" <!-- SQL 语句片段 -->
filePattern="${logdir}/$${date:yyyy-MM-dd}/error.%d{yyyy-MM-dd-HH}.log" append="true"> <!-- SQL 语句片段 -->
<PatternLayout pattern="${PATTERN}"/> <!-- SQL 语句片段 -->
<ThresholdFilter level="ERROR" onMatch="ACCEPT" onMismatch="DENY"/> <!-- SQL 语句片段 -->
<Policies> <!-- SQL 语句片段 -->
<TimeBasedTriggeringPolicy interval="1" modulate="true" /> <!-- SQL 语句片段 -->
</Policies> <!-- SQL 语句片段 -->
</RollingFile> <!-- SQL 语句片段 -->
<RollingFile name="DebugAppender" fileName="${logdir}/info.log" <!-- SQL 语句片段 -->
filePattern="${logdir}/$${date:yyyy-MM-dd}/info.%d{yyyy-MM-dd-HH}.log" append="true"> <!-- SQL 语句片段 -->
<PatternLayout pattern="${PATTERN}"/> <!-- SQL 语句片段 -->
<ThresholdFilter level="DEBUG" onMatch="ACCEPT" onMismatch="DENY"/> <!-- SQL 语句片段 -->
<Policies> <!-- SQL 语句片段 -->
<TimeBasedTriggeringPolicy interval="1" modulate="true" /> <!-- SQL 语句片段 -->
</Policies> <!-- SQL 语句片段 -->
</RollingFile> <!-- SQL 语句片段 -->
<!--异步appender-->
<Async name="AsyncAppender" includeLocation="true"> <!-- SQL 语句片段 -->
<AppenderRef ref="ErrorAppender"/> <!-- SQL 语句片段 -->
<AppenderRef ref="DebugAppender"/> <!-- SQL 语句片段 -->
</Async> <!-- SQL 语句片段 -->
</Appenders> <!-- SQL 语句片段 -->
<Loggers> <!-- SQL 语句片段 -->
<!--过滤掉spring和mybatis的一些无用的debug信息-->
<logger name="org.springframework" level="INFO"> <!-- SQL 语句片段 -->
</logger> <!-- SQL 语句片段 -->
<logger name="org.mybatis" level="INFO"> <!-- SQL 语句片段 -->
</logger> <!-- SQL 语句片段 -->
<logger name="cn.itcast.wanxinp2p.consumer.mapper" level="DEBUG"> <!-- SQL 语句片段 -->
</logger> <!-- SQL 语句片段 -->
<logger name="springfox" level="INFO"> <!-- SQL 语句片段 -->
</logger> <!-- SQL 语句片段 -->
<logger name="org.apache.http" level="INFO"> <!-- SQL 语句片段 -->
</logger> <!-- SQL 语句片段 -->
<logger name="com.netflix.discovery" level="INFO"> <!-- SQL 语句片段 -->
</logger> <!-- SQL 语句片段 -->
<logger name="RocketmqCommon" level="INFO" > <!-- SQL 语句片段 -->
</logger> <!-- SQL 语句片段 -->
<logger name="RocketmqRemoting" level="INFO" > <!-- SQL 语句片段 -->
</logger> <!-- SQL 语句片段 -->
<logger name="RocketmqClient" level="WARN"> <!-- SQL 语句片段 -->
</logger> <!-- SQL 语句片段 -->
<logger name="org.dromara.hmily" level="WARN"> <!-- SQL 语句片段 -->
</logger> <!-- SQL 语句片段 -->
<logger name="org.dromara.hmily.lottery" level="WARN"> <!-- SQL 语句片段 -->
</logger> <!-- SQL 语句片段 -->
<logger name="org.dromara.hmily.bonuspoint" level="WARN"> <!-- SQL 语句片段 -->
</logger> <!-- SQL 语句片段 -->
<!--OFF 0-->
<!--FATAL 100-->
<!--ERROR 200-->
<!--WARN 300-->
<!--INFO 400-->
<!--DEBUG 500-->
<!--TRACE 600-->
<!--ALL Integer.MAX_VALUE-->
<Root level="DEBUG" includeLocation="true"> <!-- SQL 语句片段 -->
<AppenderRef ref="AsyncAppender"/> <!-- SQL 语句片段 -->
<AppenderRef ref="Console"/> <!-- SQL 语句片段 -->
<AppenderRef ref="DebugAppender"/> <!-- SQL 语句片段 -->
</Root> <!-- SQL 语句片段 -->
</Loggers> <!-- SQL 语句片段 -->
</Configuration> <!-- SQL 语句片段 -->
文件:xuecheng-plus-checkcode/src/test/java/com/xuecheng/checkcode/XuechengPlusCheckcodeApplicationTests.java
package com.xuecheng.checkcode; // 声明类所在的包路径
import org.junit.jupiter.api.Test; // 导入 Test 类
import org.springframework.boot.test.context.SpringBootTest; // 导入 SpringBootTest 类
@SpringBootTest // 使用注解 @SpringBootTest
class XuechengPlusCheckcodeApplicationTests { // 定义 class XuechengPlusCheckcodeApplicationTests
@Test // 使用注解 @Test
void contextLoads() { // 定义方法 contextLoads(...)
} // 代码块结束
} // 代码块结束
评论
0 条
还没有评论,先写一条吧。