从0~1开发财务软件

1.获取图形验证码接口

功能要求

1、随机生成6位字符

2、将字符生成base64位格式的图片,返回给前端

3、将生成的字符存储到redis中,用匿名身份id(clientId)作为key,验证码作为value。

clientId通过/login/getClientId接口获取

4、验证码15分钟后过期

依赖包
XML 复制代码
<!-- 工具类 -->
<dependency>
  <groupId>cn.hutool</groupId>
  <artifactId>hutool-all</artifactId>
  <version>5.8.10</version>
</dependency>

<!-- redis -->
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-data-redis</artifactId>
  <version>2.7.5</version>
</dependency>

redis缓存配置并完善图形验证码接口

# redis配置
redis:
  database: 0
  port: 6379
  lettuce:
    pool:
      #连接池中最大空闲连接数为 30。这意味着连接池可以保持最多 30 个空闲的 Redis 连接,以便在需要时重用。
      max-idle: 30
      #连接池中最小空闲连接数为 10。这表示连接池至少会保持 10 个空闲连接,以便在需要时快速获取可用连接。
      min-idle: 10
      #连接池中的最大活动连接数为 30。这是指连接池在同一时间可以支持的最大活动(使用中)连接数量。
      max-active: 30
      #当连接池已用尽且达到最大活动连接数时,从连接池获取连接的最大等待时间为 10,000 毫秒(10 秒)。如果在等待时间内没有可用连接,将抛出连接超时异常。
      max-wait: 10000
    # 应用程序关闭时Lettuce 将等待最多 3 秒钟来完成关闭操作。如果超过这个时间仍未完成,则会强制关闭连接。
    shutdown-timeout: 3000
  host: 127.0.0.1

RedisTemplateDefaultConfig.java

java 复制代码
package com.bage.common.config;

import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.jsontype.impl.LaissezFaireSubTypeValidator;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;

/**
 * Redis Template 配置
 **/
@ConditionalOnProperty(prefix = "sys",name = "redis-template-config",havingValue = "true")
@Configuration
@Slf4j
public class RedisTemplateDefaultConfig<T> {
    /**
     * redisTemplate相关配置
     *
     * @param factory
     * @return
     */
    @Bean
    public RedisTemplate<String, T> redisTemplate(RedisConnectionFactory factory) {
        log.info("RedisTemplateConfig init start ...");
        RedisTemplate<String, T> template = new RedisTemplate<>();

        // 配置连接工厂
        template.setConnectionFactory(factory);

        //使用Jackson2JsonRedisSerializer来序列化和反序列化redis的value值(默认使用JDK的序列化方式)
        Jackson2JsonRedisSerializer<Object> jacksonSerializer = new Jackson2JsonRedisSerializer<>(Object.class);

        ObjectMapper om = new ObjectMapper();
        // 指定要序列化的域,field,get和set,以及修饰符范围,ANY是都有包括private和public
        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        om.activateDefaultTyping(LaissezFaireSubTypeValidator.instance, ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY);
        jacksonSerializer.setObjectMapper(om);

        // 值采用json序列化
        template.setValueSerializer(jacksonSerializer);
        // 使用StringRedisSerializer来序列化和反序列化redis的key值
        template.setKeySerializer(new StringRedisSerializer());

        // 设置hash key 和value序列化模式
        template.setHashKeySerializer(new StringRedisSerializer());
        template.setHashValueSerializer(jacksonSerializer);
        template.afterPropertiesSet();

        log.info("RedisTemplateConfig init end");
        return template;
    }
}

LoginController.java

java 复制代码
import com.bage.finance.biz.dto.form.GetBase64CodeForm;
import com.bage.finance.biz.service.MemberLoginService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiResponse;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * @author 啟王朝
 * date2024/6/6 18:24
 */
@Api(tags = "用户登录模块")
@RestController
@RequestMapping("/login")
@RequiredArgsConstructor
/**  @RequiredArgsConstructor final
 * 作用: 可以省略 @Autowired 和 @Rescuorce  需要注入包的前面必须加上final
 */
@Slf4j
public class LoginController {
    final MemberLoginService memberLoginService;

    //  获得游客登录的getClientId
    @ApiOperation(value = "获取客户端id")
    @GetMapping("/getClientId")
    public com.bage.common.dto.ApiResponse<String> getClientId() {
        String clientId = memberLoginService.getClientId();
        return com.bage.common.dto.ApiResponse.success(clientId);
    }

    /**
     * 作用:
     */
    @ApiOperation(value = "生成base64位格式的图片")
    @GetMapping("/getBase6Code")
    /**
     * 作用:    GetBase64CodeForm form  是将生成的字符存储到redis中,用匿名身份id(clientId)作为key,验证码作为value。
     * 0
     */
    //   @Validated  必须加统一拦截才能起作用
    public com.bage.common.dto.ApiResponse<String> getBase64Code(@Validated @ModelAttribute GetBase64CodeForm form) {
        //  返回的是code 为Base64的验证码图片
        String code = memberLoginService.getBase64Code(form);
        return com.bage.common.dto.ApiResponse.success(code);
    }
}

MemberLoginService.java

java 复制代码
import com.bage.finance.biz.dto.form.GetBase64CodeForm;

/**
 * @Author:啟王朝
 * @name:MemberLoginService
 * @Date:2024/6/6 18:18
 * @Filename:MemberLoginService
 */
public interface MemberLoginService {
    //  获取客户端id
    String getClientId();

    /**
     * 作用:获得Base64的图形编码
     */
    String getBase64Code(GetBase64CodeForm form);
}

MemberLoginServiceImpl.java

java 复制代码
import cn.hutool.captcha.CaptchaUtil;
import cn.hutool.captcha.LineCaptcha;
import com.bage.finance.biz.dto.form.GetBase64CodeForm;
import com.bage.finance.biz.service.MemberLoginService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.UUID;
import java.util.concurrent.TimeUnit;

import static com.bage.finance.biz.constant.RedisKeyConstant.GRAPHIC_VERIFICATION_CODE;

/**
 * @author 啟王朝
 * date2024/6/6 18:19
 */
@Service
@Slf4j
@RequiredArgsConstructor //  构造参数的注解
public class MemberLoginServiceImpl implements MemberLoginService {
    final RedisTemplate<String, String> redisTemplate;

    /**
     * @Date:获取客户端id // date变量下面会用内置函数进行赋值
     * @Author:
     * @return:
     */
    @Override
    public String getClientId() {
        return UUID.randomUUID().toString().replace("-", "");
    }


    /**
     * 作用:获取图形验证码界面
     */
    @Override
    public String getBase64Code(GetBase64CodeForm form) {
        //  TODO  CaptchaUtil  用工具形成验证码图片
        /**
         * 作用:
         * <dependency>
         *   <groupId>cn.hutool</groupId>
         *   <artifactId>hutool-all</artifactId>
         *   <version>5.8.10</version>
         * </dependency>
         *   300,192代表长和宽   5 代表5个字符   lineCount的数字越大,代表的数字越模糊 1000
         */
        LineCaptcha lineCaptcha = CaptchaUtil.createLineCaptcha(300, 192, 5, 1000);
        //  将验证码内容读出来
        String code = lineCaptcha.getCode();
        //  todo 将验证码保存到redis中
        redisTemplate.opsForValue().set(GRAPHIC_VERIFICATION_CODE + form.getClientId(), code,15, TimeUnit.MINUTES);
        //  返回base64的图形验证码
        return lineCaptcha.getImageBase64();
    }
}
相关推荐
Daniel 大东39 分钟前
BugJson因为json格式问题OOM怎么办
java·安全
Theodore_10225 小时前
4 设计模式原则之接口隔离原则
java·开发语言·设计模式·java-ee·接口隔离原则·javaee
冰帝海岸6 小时前
01-spring security认证笔记
java·笔记·spring
世间万物皆对象6 小时前
Spring Boot核心概念:日志管理
java·spring boot·单元测试
没书读了7 小时前
ssm框架-spring-spring声明式事务
java·数据库·spring
jokerest1237 小时前
web——sqliabs靶场——第十三关——报错注入+布尔盲注
mybatis
小二·7 小时前
java基础面试题笔记(基础篇)
java·笔记·python
开心工作室_kaic7 小时前
ssm161基于web的资源共享平台的共享与开发+jsp(论文+源码)_kaic
java·开发语言·前端
懒洋洋大魔王7 小时前
RocketMQ的使⽤
java·rocketmq·java-rocketmq
武子康7 小时前
Java-06 深入浅出 MyBatis - 一对一模型 SqlMapConfig 与 Mapper 详细讲解测试
java·开发语言·数据仓库·sql·mybatis·springboot·springcloud