6、发送验证码功能(Redis)

一、业务需求:

6、发送验证码功能(Redis)

1、后端随机生成短信验证码,并在服务器端保存一定时间(redis);

2、将短信验证码发给用户;

3、用户输入短信验证码提交后,在后端与之前生成的短信验证码作比较,如果相同说明验证成功,否则验证失败。

二、操作流程:

Redis笔记参考

建工程——》改POM——》写YML——》业务类

1、添加依赖:

org.springframework.boot
            spring-boot-starter-data-redis

            com.aliyun
            aliyun-java-sdk-core
            4.0.6

            com.aliyun
            aliyun-java-sdk-dysmsapi
            1.1.0

            javax.mail
            mail
            1.4.7

2、写YML:

server:
  port: 8081

spring:
  application:
    name: demo
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource    #当前数据源操作类型
    driver-class-name: org.gjt.mm.mysql.Driver    #mysql驱动包
    url: jdbc:mysql://localhost:3306/demo?useUnicode=true&characterEncoding=utf-8&useSSL=false
    username: root
    password: 123456
    druid:
      test-while-idle: false  #关闭空闲检测
  redis:
    host: 127.0.0.1   # Redis服务器地址
    port: 6379    # Redis服务器连接端口
    password:   # Redis服务器连接密码
    jedis:
      pool:
        max-active: 8   # 连接池最大连接数(使用负值表示没有限制)
        max-wait: -1ms    # 连接池最大阻塞等待时间(使用负值表示没有限制)
        max-idle: 500   # 连接池中的最大空闲连接
        min-idle: 0   # 连接池中的最小空闲连接
    lettuce:
      shutdown-timeout: 0ms

mybatis:
  mapperLocations: classpath:mapper/*.xml

三、通用工具类:

1、Redis通用工具类:

@Component
public final class RedisUtil {

    @Autowired
    private RedisTemplate redisTemplate;

    // =============================common============================
    /**
     * 指定缓存失效时间
     * @param key  键
     * @param time 时间(秒)
     */
    public boolean expire(String key, long time) {
        try {
            if (time > 0) {
                redisTemplate.expire(key, time, TimeUnit.SECONDS);
            }
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 根据key 获取过期时间
     * @param key 键 不能为null
     * @return 时间(秒) 返回0代表为永久有效
     */
    public long getExpire(String key) {
        return redisTemplate.getExpire(key, TimeUnit.SECONDS);
    }

    /**
     * 判断key是否存在
     * @param key 键
     * @return true 存在 false不存在
     */
    public boolean hasKey(String key) {
        try {
            return redisTemplate.hasKey(key);
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 删除缓存
     * @param key 传入一个值
     */
    @SuppressWarnings("unchecked")
    public void del(String key) {
        redisTemplate.delete(key);
    }

    /**
     * 删除缓存
     * @param keys 传入多个值
     */
    @SuppressWarnings("unchecked")
    public void del(Collection keys) {
        redisTemplate.delete(keys);
    }

    // ============================String=============================

    /**
     * 普通缓存获取
     * @param key 键
     * @return*/
    public Object get(String key) {
        return key == null ? null : redisTemplate.opsForValue().get(key);
    }

    /**
     * 普通缓存放入
     * @param key   键
     * @param value 值
     * @return true成功 false失败
     */

    public boolean set(String key, Object value) {
        try {
            redisTemplate.opsForValue().set(key, value);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 普通缓存放入并设置时间
     * @param key   键
     * @param value 值
     * @param time  时间(秒) time要大于0 如果time小于等于0 将设置无限期
     * @return true成功 false 失败
     */

    public boolean set(String key, Object value, long time) {
        try {
            if (time > 0) {
                redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS);
            } else {
                set(key, value);
            }
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 递增
     * @param key   键
     * @param delta 要增加几(大于0)
     */
    public long incr(String key, long delta) {
        if (delta < 0) {
            throw new RuntimeException("递增因子必须大于0");
        }
        return redisTemplate.opsForValue().increment(key, delta);
    }

    /**
     * 递减
     * @param key   键
     * @param delta 要减少几(小于0)
     */
    public long decr(String key, long delta) {
        if (delta < 0) {
            throw new RuntimeException("递减因子必须大于0");
        }
        return redisTemplate.opsForValue().increment(key, -delta);
    }

    // ================================Map=================================

    /**
     * HashGet
     * @param key  键 不能为null
     * @param item 项 不能为null
     */
    public Object hget(String key, String item) {
        return redisTemplate.opsForHash().get(key, item);
    }

    /**
     * 获取hashKey对应的所有键值
     * @param key 键
     * @return 对应的多个键值
     */
    public Map hmget(String key) {
        return redisTemplate.opsForHash().entries(key);
    }

    /**
     * HashSet
     * @param key 键
     * @param map 对应多个键值
     */
    public boolean hmset(String key, Map map) {
        try {
            redisTemplate.opsForHash().putAll(key, map);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * HashSet 并设置时间
     * @param key  键
     * @param map  对应多个键值
     * @param time 时间(秒)
     * @return true成功 false失败
     */
    public boolean hmset(String key, Map map, long time) {
        try {
            redisTemplate.opsForHash().putAll(key, map);
            if (time > 0) {
                expire(key, time);
            }
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 向一张hash表中放入数据,如果不存在将创建
     *
     * @param key   键
     * @param item  项
     * @param value 值
     * @return true 成功 false失败
     */
    public boolean hset(String key, String item, Object value) {
        try {
            redisTemplate.opsForHash().put(key, item, value);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 向一张hash表中放入数据,如果不存在将创建
     *
     * @param key   键
     * @param item  项
     * @param value 值
     * @param time  时间(秒) 注意:如果已存在的hash表有时间,这里将会替换原有的时间
     * @return true 成功 false失败
     */
    public boolean hset(String key, String item, Object value, long time) {
        try {
            redisTemplate.opsForHash().put(key, item, value);
            if (time > 0) {
                expire(key, time);
            }
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 删除hash表中的值
     *
     * @param key  键 不能为null
     * @param item 项 可以使多个 不能为null
     */
    public void hdel(String key, Object... item) {
        redisTemplate.opsForHash().delete(key, item);
    }

    /**
     * 判断hash表中是否有该项的值
     *
     * @param key  键 不能为null
     * @param item 项 不能为null
     * @return true 存在 false不存在
     */
    public boolean hHasKey(String key, String item) {
        return redisTemplate.opsForHash().hasKey(key, item);
    }

    /**
     * hash递增 如果不存在,就会创建一个 并把新增后的值返回
     *
     * @param key  键
     * @param item 项
     * @param by   要增加几(大于0)
     */
    public double hincr(String key, String item, double by) {
        return redisTemplate.opsForHash().increment(key, item, by);
    }

    /**
     * hash递减
     *
     * @param key  键
     * @param item 项
     * @param by   要减少记(小于0)
     */
    public double hdecr(String key, String item, double by) {
        return redisTemplate.opsForHash().increment(key, item, -by);
    }

    // ============================set=============================

    /**
     * 根据key获取Set中的所有值
     * @param key 键
     */
    public Set sGet(String key) {
        try {
            return redisTemplate.opsForSet().members(key);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 根据value从一个set中查询,是否存在
     *
     * @param key   键
     * @param value 值
     * @return true 存在 false不存在
     */
    public boolean sHasKey(String key, Object value) {
        try {
            return redisTemplate.opsForSet().isMember(key, value);
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 将数据放入set缓存
     *
     * @param key    键
     * @param values 值 可以是多个
     * @return 成功个数
     */
    public long sSet(String key, Object... values) {
        try {
            return redisTemplate.opsForSet().add(key, values);
        } catch (Exception e) {
            e.printStackTrace();
            return 0;
        }
    }

    /**
     * 将set数据放入缓存
     *
     * @param key    键
     * @param time   时间(秒)
     * @param values 值 可以是多个
     * @return 成功个数
     */
    public long sSetAndTime(String key, long time, Object... values) {
        try {
            Long count = redisTemplate.opsForSet().add(key, values);
            if (time > 0)
                expire(key, time);
            return count;
        } catch (Exception e) {
            e.printStackTrace();
            return 0;
        }
    }

    /**
     * 获取set缓存的长度
     *
     * @param key 键
     */
    public long sGetSetSize(String key) {
        try {
            return redisTemplate.opsForSet().size(key);
        } catch (Exception e) {
            e.printStackTrace();
            return 0;
        }
    }

    /**
     * 移除值为value的
     *
     * @param key    键
     * @param values 值 可以是多个
     * @return 移除的个数
     */

    public long setRemove(String key, Object... values) {
        try {
            Long count = redisTemplate.opsForSet().remove(key, values);
            return count;
        } catch (Exception e) {
            e.printStackTrace();
            return 0;
        }
    }

    // ===============================list=================================

    /**
     * 获取list缓存的内容
     *
     * @param key   键
     * @param start 开始
     * @param end   结束 0 到 -1代表所有值
     */
    public List lGet(String key, long start, long end) {
        try {
            return redisTemplate.opsForList().range(key, start, end);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 获取list缓存的长度
     *
     * @param key 键
     */
    public long lGetListSize(String key) {
        try {
            return redisTemplate.opsForList().size(key);
        } catch (Exception e) {
            e.printStackTrace();
            return 0;
        }
    }

    /**
     * 通过索引 获取list中的值
     *
     * @param key   键
     * @param index 索引 index>=0时, 0 表头,1 第二个元素,依次类推;index*/
    public Object lGetIndex(String key, long index) {
        try {
            return redisTemplate.opsForList().index(key, index);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 将list放入缓存
     *
     * @param key   键
     * @param value 值
     */
    public boolean lSet(String key, Object value) {
        try {
            redisTemplate.opsForList().rightPush(key, value);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 将list放入缓存
     * @param key   键
     * @param value 值
     * @param time  时间(秒)
     */
    public boolean lSet(String key, Object value, long time) {
        try {
            redisTemplate.opsForList().rightPush(key, value);
            if (time > 0)
                expire(key, time);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }

    }

    /**
     * 将list放入缓存
     *
     * @param key   键
     * @param value 值
     * @return
     */
    public boolean lSet(String key, List value) {
        try {
            redisTemplate.opsForList().rightPushAll(key, value);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }

    }

    /**
     * 将list放入缓存
     *
     * @param key   键
     * @param value 值
     * @param time  时间(秒)
     * @return
     */
    public boolean lSet(String key, List value, long time) {
        try {
            redisTemplate.opsForList().rightPushAll(key, value);
            if (time > 0)
                expire(key, time);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 根据索引修改list中的某条数据
     *
     * @param key   键
     * @param index 索引
     * @param value 值
     * @return
     */

    public boolean lUpdateIndex(String key, long index, Object value) {
        try {
            redisTemplate.opsForList().set(key, index, value);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 移除N个值为value
     *
     * @param key   键
     * @param count 移除多少个
     * @param value 值
     * @return 移除的个数
     */

    public long lRemove(String key, long count, Object value) {
        try {
            Long remove = redisTemplate.opsForList().remove(key, count, value);
            return remove;
        } catch (Exception e) {
            e.printStackTrace();
            return 0;
        }

    }
},>,>,>,>

2、随机数工具类:

public class RandomUtil {

    //随机生成六位数验证码
    public static String getCode() {
        Random random = new Random();
        String result = "";
        for (int i = 0; i < 6; i++) {
            result += random.nextInt(10);
        }
        return result;
    }
}

3、发送信息工具类:

public class SentMessageUtil {
    /**
     * 发送短信信息
     * */
    //产品名称:云通信短信API产品,开发者无需替换
    static final String product = "Dysmsapi";
    //产品域名,开发者无需替换
    static final String domain = "dysmsapi.aliyuncs.com";
    // TODO 此处需要替换成开发者自己的AK(在阿里云访问控制台寻找)
    static final String accessKeyId = "自己的AccessKeyId";
    static final String accessKeySecret = "自己的accesskeySecret";

    public static boolean sendMessage(String id, String code) {
        //可自助调整超时时间
        System.setProperty("sun.net.client.defaultConnectTimeout", "10000");
        System.setProperty("sun.net.client.defaultReadTimeout", "10000");
        //初始化acsClient,暂不支持region化
        IClientProfile profile = DefaultProfile.getProfile("cn-hangzhou", accessKeyId, accessKeySecret);
        try {
            DefaultProfile.addEndpoint("cn-hangzhou", "cn-hangzhou", product, domain);
            IAcsClient acsClient = new DefaultAcsClient(profile);

            //组装请求对象-具体描述见控制台-文档部分内容
            SendSmsRequest request = new SendSmsRequest();
            //必填:待发送手机号
            request.setPhoneNumbers(id);
            //必填:短信签名-可在短信控制台中找到
            request.setSignName("替换成自己的短信签名");
            //必填:短信模板-可在短信控制台中找到
            request.setTemplateCode("替换成自己的短信模板编号");
            //可选:模板中的变量替换JSON串,如模板内容为"亲爱的${name},您的验证码为${code}"时,此处的值为
            request.setTemplateParam(code);
            SendSmsResponse sendSmsResponse = acsClient.getAcsResponse(request);
            if( sendSmsResponse.getCode().equals("OK")) {
                return true;
            }else {
                return false;
            }
        } catch (ClientException e) {
            e.printStackTrace();
        }
        return false;
    }

    /**
     * 发送邮件信息
     * */
    public static boolean sendMail(String id, String code) {
        Properties properties = new Properties();
        // 连接协议
        properties.put("mail.transport.protocol", "smtp");
        // 主机名
        properties.put("mail.smtp.host", "smtp.qq.com");
        // 端口号
        properties.put("mail.smtp.port", 465);
        properties.put("mail.smtp.auth", "true");
        // 设置是否使用ssl安全连接 ---一般都使用
        properties.put("mail.smtp.ssl.enable", "true");
        // 设置是否显示debug信息 true 会在控制台显示相关信息
        properties.put("mail.debug", "true");
        // 得到回话对象
        Session session = Session.getInstance(properties);
        // 获取邮件对象
        Message message = new MimeMessage(session);
        try {
            // 设置发件人邮箱地址
            message.setFrom(new InternetAddress("发件人xxx@qq.com"));
            // 设置收件人邮箱地址:单个/多个
            //message.setRecipients(Message.RecipientType.TO, new InternetAddress[]{new InternetAddress("xxx@qq.com"),new InternetAddress("xxx@qq.com"),new InternetAddress("xxx@qq.com")});
            message.setRecipient(Message.RecipientType.TO, new InternetAddress(id));
            // 设置邮件标题
            message.setSubject("验证信息测试");
            // 设置邮件内容
            message.setText("验证码为:" + code + ",验证码有效期5分钟,请及时验证");
            // 得到邮差对象
            Transport transport = session.getTransport();
            // 连接自己的邮箱账户
            // 密码为QQ邮箱开通的stmp服务后得到的客户端授权码
            transport.connect("发件人xxx@qq.com", "rbg");
            // 发送邮件
            transport.sendMessage(message, message.getAllRecipients());
            transport.close();
            return true;
        } catch (MessagingException e) {
            e.printStackTrace();
        }
        return false;
    }
}

4、Redis配置类:

@EnableCaching
@Configuration
public class RedisConfig extends CachingConfigurerSupport {

    /**
     * RedisTemplate内部的序列化配置器默认采用JDK序列化器
     * 使用默认序列化配置器查看数据时会导致数据乱码,需重新定义RedisTemplate序列化方案
     * 修改存储对象的序列化问题
     */
    @Bean
    @SuppressWarnings("all")
    public RedisTemplate redisTemplate(RedisConnectionFactory factory) {
        RedisTemplate template = new RedisTemplate();
        template.setConnectionFactory(factory);
        Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
        ObjectMapper om = new ObjectMapper();
        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        jackson2JsonRedisSerializer.setObjectMapper(om);
        StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();

        // key采用String的序列化方式
        template.setKeySerializer(stringRedisSerializer);
        // hash的key也采用String的序列化方式
        template.setHashKeySerializer(stringRedisSerializer);
        // value序列化方式采用jackson
        template.setValueSerializer(jackson2JsonRedisSerializer);
        // hash的value序列化方式采用jackson
        template.setHashValueSerializer(jackson2JsonRedisSerializer);
        template.afterPropertiesSet();

        return template;
    }

    /**
     * CacheManager:
     * 管理多种缓存,包含内存, appfabric, redis, couchbase, windows azure cache, memorycache等
     * 提供了额外的功能,如缓存同步、并发更新、事件、性能计数器等
     */
    @Bean
    public CacheManager cacheManager(RedisConnectionFactory factory) {
        RedisSerializer redisSerializer = new StringRedisSerializer();
        Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
        //解决查询缓存转换异常的问题
        ObjectMapper om = new ObjectMapper();
        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        jackson2JsonRedisSerializer.setObjectMapper(om);
        // 配置序列化(解决乱码的问题),过期时间600秒
        RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
                .entryTtl(Duration.ofSeconds(600))
                .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(redisSerializer))
                .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(jackson2JsonRedisSerializer))
                .disableCachingNullValues();
        RedisCacheManager cacheManager = RedisCacheManager.builder(factory)
                .cacheDefaults(config)
                .build();
        return cacheManager;
    }

}

四、发送验证码功能:

1、请求体:

@Data
public class MessageResourceVO {

    private String id;

    private String code;

    private Boolean way;

}

2、控制类:

/**
     * 功能一:发送验证码
     *
     * http://localhost:8081/v1/sent-code
     * */
    @PostMapping("/sent-code")
    public Response sentCode(
            @RequestBody MessageResourceVO messageResourceVO) {
        return Response.success(sendService.sentCode(messageResourceVO));
    }

3、业务类:

@Autowired
    private RedisUtil redisUtil;

    @Override
    public Object sentCode(MessageResourceVO messageResourceVO) {
        //设置redis的key:USER:+号码
        String userId = "USER:" + messageResourceVO.getId();
        //设置redis的value:随机生成的六位数验证码
        String code = RandomUtil.getCode();
        //设置验证码的失效时间:5min-->300s
        redisUtil.set(userId,code,300);
        //判断key是否存在
        if (redisUtil.hasKey(userId)) {
            boolean isSuccess = false;
            if (messageResourceVO.getWay()) {
                //发送短信验证码
                isSuccess = SentMessageUtil.sendMessage(messageResourceVO.getId(), code);
            } else {
                //发送邮件验证码
                isSuccess = SentMessageUtil.sendMail(messageResourceVO.getId(), code);
            }
            if (isSuccess) {
                return "success";
            } else {
                return "fail";
            }
        } else {
            return "redis连接失败";
        }
    }

五、验证信息功能:

1、请求体:

@Data
public class MessageResourceVO {

    private String id;

    private String code;

    private Boolean way;

}

2、控制类:

/**
     * 功能二:验证信息
     *
     * http://localhost:8081/v1/verify-code
     * */
    @PostMapping("/verify-code")
    public Response verifyCode(
            @RequestBody MessageResourceVO messageResourceVO) {
        return Response.success(sendService.verifyCode(messageResourceVO));
    }

3、业务类:

@Autowired
    private RedisUtil redisUtil;

    @Override
    public Object verifyCode(MessageResourceVO messageResourceVO) {
        //设置redis的key:USER:+号码
        String userId = "USER:" + messageResourceVO.getId();
        //获取Redis缓存值
        String realCode = redisUtil.get(userId).toString();
        if(realCode != null && realCode.equals(messageResourceVO.getCode())){
            return "success";
        }else {
            return "fail";
        }
    }

六、参考:

1、发送邮件参考

2、 阿里云服务发送手机短信验证码参考

3、邮件、短信的发送功能参考

4、 阿里云短信服务参考

搜索

复制

Original: https://www.cnblogs.com/Iven-L/p/16587484.html
Author: 爱文(Iven)
Title: 6、发送验证码功能(Redis)

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/575697/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • 数据库性能优化八大方案,你知道几个

    前言 毫不夸张的说咱们后端工程师,无论在哪家公司,呆在哪个团队,做哪个系统,遇到的第一个让人头疼的问题绝对是数据库性能问题。 如果我们有一套成熟的方法论,能让大家快速、准确的去选择…

    数据库 2023年6月14日
    071
  • 真正在大厂干了几年,我学会了反内卷[转]

    内卷这个概念的内涵很丰富,与我们的生活息息相关。为了普及和传播知识,我参考了相关的信息,把我个人的粗浅理解奉献给朋友们。 什么是内卷? 内卷 involution,与之对应的是 e…

    数据库 2023年6月14日
    0103
  • 由delete引起的锁扩大

    由delete引起的锁扩大 阿里云月报中的一句话,出处:http://mysql.taobao.org/monthly/2022/01/01/ 但是Ghost Record是可以跟…

    数据库 2023年5月24日
    090
  • 绿色安装MySQL5.7版本—-配置my.ini文件注意事项

    简述绿色安装MySQL5.7版本以及配置my.ini文件注意事项 前言 由于前段时间电脑重装,虽然很多软件不在C盘,但是由于很多注册表以及关联文件被删除,很多软件还需要重新配置甚至…

    数据库 2023年6月16日
    089
  • Redis+Lua实现简易的秒杀抢购

    1 商品抢购 主要逻辑是:减库存,记录抢购成功的用户 @RestController public class DemoController { @Resource private…

    数据库 2023年6月14日
    0102
  • Git 环境搭建

    安装 Git:官网 👉https://git-scm.com/ GIt基础配置(以下操作均在 git bash 窗口下进行) git config –global user.na…

    数据库 2023年6月6日
    068
  • SQLZOO练习7–Using NULL

    teacher表: iddeptnamephonemobile 101 1 Shrivell 2753 07986 555 1234 102 1 Throd 2754 07122 …

    数据库 2023年5月24日
    068
  • ShardingSphere 异构迁移最佳实践:将3.5亿量级的顾客系统 RTO 减少60倍

    Apache ShardingSphere 助力当当 3.5 亿用户量级顾客系统重构,由 PHP+SQL Server 技术栈无缝转型为 Java+ShardingSphere+M…

    数据库 2023年6月16日
    0103
  • 删除chrome的域名安全策略

    使用过程中总有特殊情况必须使用http请求、又或者必须使用https请求 目前有两种思路,一种是浏览器默认开了http转https请求,像chrome和Firefox,另一种就是服…

    数据库 2023年6月6日
    088
  • MySQL源码分析之SQL函数执行

    1.MySQL中执行一条SQL的总体流程 2.SQL函数执行过程 1.MySQL中执行一条SQL的总体流程 一条包含函数的SQL语句,在mysql中会经过: &#x5BA2…

    数据库 2023年5月24日
    091
  • 第16章 变量、流程控制与游标

    第16章 变量、流程控制与游标 1. 变量 在MySQL数据库的存储过程和函数中,可以使用变量来存储查询或计算的中间结果数据,或者输出最终的结果数据。 在 MySQL 数据库中,变…

    数据库 2023年6月6日
    083
  • MySQL 日志管理

    日志文件记录 MySQL 数据库运行期间发生的变化,当数据库遭到意外的损害时,可以通过日志文件查询出错原因,并进件数据恢复 MySQL 日志文件可以分成以下几类: 二进制日志:记录…

    数据库 2023年5月24日
    054
  • Atlas快速入门

    之前的公司在数据中台的项目上调研决定启用了Atlas作为我们数据血缘管理的工具,让我给大家写了一份Atlas快速入门的文档,所以在这里我将这篇文档以一个纯新手视角的方式再一次优化,…

    数据库 2023年6月11日
    086
  • 使用mybatis连接数据库–针对小白

    实现mybatis连接数据库的步骤: 1.建表 2.pom.xml的配置 <?xml version="1.0" encoding="UTF-8…

    数据库 2023年6月11日
    051
  • 数据库多表查询 联合查询 增删改查

    插入 方式一 语法: insert into 表名 (字段名,…) values (值,…); 特点: 1、要求值的类型和字段的类型要一致或兼容 2、字段的个数和顺序不一定…

    数据库 2023年6月16日
    0136
  • 老板:把系统从单体架构升级到集群架构!

    首发于公众号:BiggerBoy 如题,本文针对工作中实际经验,整理了把一个单体架构的系统升级成集群架构需要做的准备工作,以及为集群架构的升级做指导方针。 本文首先分析了单体架构存…

    数据库 2023年6月11日
    070
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球