高并发项目-用户登录基本功能

news2024/11/8 11:18:39

文章目录

    • 1.数据库表设计
        • 1.IDEA连接数据库
        • 2.修改application.yml中数据库的名称为seckill
        • 3.IDEA创建数据库seckill
        • 4.创建数据表 seckill_user
        • 5.密码加密分析
          • 1.传统方式(不安全)
          • 2.改进方式(两次加密加盐)
    • 2.密码加密功能实现
        • 1.pom.xml添加md5加密的依赖,刷新maven
        • 2.编写工具类MD5Util.java,完成加密
        • 3.测试
          • 1.引入jupiter 5.7.2依赖
          • 2.测试方法
    • 3.编写实体类映射表
        • 1.创建pojo目录
        • 2.User.java
    • 4.创建Mapper接口和Mapper.xml
        • 1.创建UserMapper.java
        • 2.创建UserMapper.xml
    • 5.响应信息类
        • 1.创建vo目录
        • 2.RespBeanEnum.java 响应信息枚举类
        • 3.RespBean.java 响应信息的Bean
    • 6.编写接受登录信息的vo以及手机号校验工具类
        • 1.LoginVo.java
        • 2.ValidatorUtil.java
    • 7.编写service层
        • 1.UserService.java
        • 2.UserServiceImpl.java
    • 8.编写controller层
        • 1.引入校验的依赖
        • 2.LoginController.java
        • 3.引入静态资源和模板页
        • 4.解析前端登录
          • 1.点击登录,调用login
          • 2.将密码加密加盐之后向后端 /login/doLogin 发送请求
        • 5.测试访问首页
          • 1.首先检查资源是否到了target目录,如果没到需要maven重新编译
          • 2.测试访问 http://localhost:9092/seckill/login/toLogin
        • 6.前端区分多环境
          • 1.可以看到前端请求时使用的`/`其实只是本机的服务发现,也就是http://localhost:9092/,所以需要区分多环境
          • 2.首先新增一个配置类 GlobalControllerAdvice.java 全局控制器通知,用于向前端传递全局变量
          • 3.在application.yml和application-prod.yml编写baseUrl,区分多环境
          • 4.login.html 读取baseUrl
            • 1.在script标签内添加一行代码使其能够解析Thymeleaf
            • 2.修改请求,格式为 baseUrl + 资源路径
        • 7.在数据库添加一条记录,可以模拟用户登录
          • 1.假设密码是admin,在前端输出一下第一次加密加盐的结果
          • 2.使用后端的工具类也来加密一下,比对结果,发现结果一致
          • 3.在第二次加密的时候重新设置一个不同的盐为niubi666,模拟不同用户
          • 4.将结果放到数据库中
          • 5.此时的用户名和密码
        • 8.编写登录的controller并测试
          • 1.LoginController.java
          • 2.测试,登录成功

1.数据库表设计

1.IDEA连接数据库
2.修改application.yml中数据库的名称为seckill
3.IDEA创建数据库seckill

image-20240505140758642

4.创建数据表 seckill_user
DROP TABLE IF EXISTS `seckill_user`;
CREATE TABLE `seckill_user`
(
    `id`              BIGINT(20)   NOT NULL COMMENT '用户 ID, 设为主键, 唯一 手机号',
    `nickname`        VARCHAR(255) NOT NULL DEFAULT '',
    `password`        VARCHAR(32)  NOT NULL DEFAULT '' COMMENT 'MD5(MD5(pass 明文+固定salt)+salt)',
    `slat`            VARCHAR(10)  NOT NULL DEFAULT '',
    `head`            VARCHAR(128) NOT NULL DEFAULT '' COMMENT '头像',
    `register_date`   DATETIME              DEFAULT NULL COMMENT '注册时间',
    `last_login_date` DATETIME              DEFAULT NULL COMMENT '最后一次登录时间',
    `login_count`     INT(11)               DEFAULT '0' COMMENT '登录次数',
    PRIMARY KEY (`id`)
) ENGINE = INNODB DEFAULT CHARSET = utf8mb4;
select * from seckill_user;
5.密码加密分析
1.传统方式(不安全)

image-20240505141421491

2.改进方式(两次加密加盐)

image-20240505142002927

2.密码加密功能实现

1.pom.xml添加md5加密的依赖,刷新maven
    <!--md5 依赖-->
    <dependency>
      <groupId>commons-codec</groupId>
      <artifactId>commons-codec</artifactId>
      <version>1.15</version>
    </dependency>
    <dependency>
      <groupId>org.apache.commons</groupId>
      <artifactId>commons-lang3</artifactId>
      <version>3.11</version>
    </dependency>

2.编写工具类MD5Util.java,完成加密
package com.sxs.seckill.utils;

import org.apache.commons.codec.digest.DigestUtils;

/**
 * Description: MD5加密工具类
 *
 * @Author sun
 * @Create 2024/5/5 14:23
 * @Version 1.0
 */
public class MD5Util {
    /**
     * 将一个字符串转换为MD5
     * @param src
     * @return
     */
    public static String md5(String src) {
        return DigestUtils.md5Hex(src);
    }

    // 固定的salt
    public static final String SALT = "dgeb2g4t";
    // 第一次加密加盐
    public static String inputPassToMidPass(String inputPass) {
        // 加盐
        String str = SALT.charAt(0) + inputPass + SALT.charAt(6);
        return md5(str);
    }

    /**
     * 第二次加密加盐
     * @param midPass
     * @param salt
     * @return
     */
    public static String midPassToDBPass(String midPass, String salt) {
        String str = salt.charAt(0) + midPass + salt.charAt(5);
        return md5(str);
    }

    /**
     * 两次加密
     * @param input
     * @param saltDB
     * @return
     */
    public static String inputPassToDBPass(String input, String saltDB) {
        String midPass = inputPassToMidPass(input);
        String dbPass = midPassToDBPass(midPass, saltDB);
        return dbPass;
    }
}

3.测试
1.引入jupiter 5.7.2依赖
    <!-- jupiter测试 -->
    <dependency>
      <groupId>org.junit.jupiter</groupId>
      <artifactId>junit-jupiter-api</artifactId>
      <version>5.7.2</version>
      <scope>compile</scope>
    </dependency>
2.测试方法
package com.sxs.seckill.utils;

/**
 * Description: 测试MD5加密方法
 *
 * @Author sun
 * @Create 2024/5/5 14:47
 * @Version 1.0
 */
public class MD5UtilTest {
    public static void main(String[] args) {
        String input = "123456";
        System.out.println("第一次加密:" + MD5Util.inputPassToMidPass(input));
        System.out.println("第二次加密:" + MD5Util.midPassToDBPass(MD5Util.inputPassToMidPass(input), MD5Util.SALT));
        System.out.println("两次加密:" + MD5Util.inputPassToDBPass(input, MD5Util.SALT));
    }
}

image-20240505145723067

3.编写实体类映射表

1.创建pojo目录

image-20240505145913793

2.User.java
package com.sxs.seckill.pojo;

import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;

import java.io.Serializable;
import java.util.Date;

/**
 * Description:
 *
 * @Author sun
 * @Create 2024/5/5 14:59
 * @Version 1.0
 */
@Data
@TableName("seckill_user") // 指定表名
public class User implements Serializable { // 实现序列化接口
    private static final long serialVersionUID = 1L;
    /**
     * 用户 ID是手机号码
     */
    @TableId(value = "id", type = IdType.ASSIGN_ID) // 指定主键,IdType.ASSIGN_ID表示自己指定ID,不自增
    private Long id;
    private String nickname;
    /**
     * MD5(MD5(pass 明文+固定 salt)+salt)
     */
    private String password;
    private String slat;
    /**
     * 头像
     */
    private String head;
    /**
     * 注册时间
     */
    private Date registerDate;
    /**
     * 最后一次登录时间
     */
    private Date lastLoginDate;
    /**
     * 登录次数
     */
    private Integer loginCount;
}

4.创建Mapper接口和Mapper.xml

1.创建UserMapper.java
package com.sxs.seckill.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.sxs.seckill.pojo.User;

/**
 * Description:
 *
 * @Author sun
 * @Create 2024/5/5 15:04
 * @Version 1.0
 */
public interface UserMapper extends BaseMapper<User> {
}

2.创建UserMapper.xml
<?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="com.sxs.seckill.mapper.UserMapper">
    <!-- 通用查询映射结果 -->
    <resultMap id="BaseResultMap" type="com.sxs.seckill.pojo.User">
        <id column="id" property="id"/>
        <result column="nickname" property="nickname"/>
        <result column="password" property="password"/>
        <result column="slat" property="slat"/>
        <result column="head" property="head"/>
        <result column="register_date" property="registerDate"/>
        <result column="last_login_date" property="lastLoginDate"/>
        <result column="login_count" property="loginCount"/>
    </resultMap>
</mapper>

5.响应信息类

1.创建vo目录

image-20240505152351330

2.RespBeanEnum.java 响应信息枚举类
package com.sxs.seckill.vo;

import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.ToString;

/**
 * Description: 响应枚举类
 *
 * @Author sun
 * @Create 2024/5/5 15:15
 * @Version 1.0
 */

@Getter
@AllArgsConstructor
@ToString
public enum RespBeanEnum {
    // 通用
    SUCCESS(200, "SUCCESS"),
    ERROR(500, "服务端异常"),
    //登录模块
    LOGIN_ERROR(500210, "用户名或者密码错误"),
    MOBILE_ERROR(500211, "手机号码格式不正确"), 
    BING_ERROR(500212, "参数绑定异常"), 
    MOBILE_NOT_EXIST(500213, "手机号码不存在"), 
    PASSWORD_UPDATE_FAIL(500214, "更新密码失败");

    // 响应码和响应信息
    private final Integer code;
    private final String message;

}

3.RespBean.java 响应信息的Bean
package com.sxs.seckill.vo;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

/**
 * Description:
 *
 * @Author sun
 * @Create 2024/5/5 15:32
 * @Version 1.0
 */
@Data
@NoArgsConstructor
@AllArgsConstructor
public class RespBean {
    private long code;
    private String message;
    private Object obj;

    // 成功后
    public static RespBean success(Object obj) {
        return new RespBean(RespBeanEnum.SUCCESS.getCode(), RespBeanEnum.SUCCESS.getMessage(), obj);
    }

    public static RespBean success() {
        return new RespBean(RespBeanEnum.SUCCESS.getCode(), RespBeanEnum.SUCCESS.getMessage(), null);
    }

    // 失败各有不同
    public static RespBean error(RespBeanEnum respBeanEnum) {
        return new RespBean(respBeanEnum.getCode(), respBeanEnum.getMessage(), null);
    }

    public static RespBean error(RespBeanEnum respBeanEnum, Object obj) {
        return new RespBean(respBeanEnum.getCode(), respBeanEnum.getMessage(), obj);
    }
}

6.编写接受登录信息的vo以及手机号校验工具类

1.LoginVo.java
package com.sxs.seckill.vo;

/**
 * Description: 登录实体类
 *
 * @Author sun
 * @Create 2024/5/5 15:43
 * @Version 1.0
 */
public class LoginVo {
    private String mobile;
    private String password;
}

2.ValidatorUtil.java
package com.sxs.seckill.utils;

import org.junit.jupiter.api.Test;

/**
 * Description: 校验工具类
 *
 * @Author sun
 * @Create 2024/5/5 15:45
 * @Version 1.0
 */
public class ValidatorUtil {
    /**
     * 校验手机号是否有效
     * @param phoneNumber 手机号
     * @return 如果手机号有效返回 true,否则返回 false
     */
    public static boolean isMobile(String phoneNumber) {
        // 中国大陆的手机号码正则表达式,要求是11位数字,以1开头,第二位是3-9,后面是任意数字共11位
        String regex = "^1[3-9]\\d{9}$";
        return phoneNumber.matches(regex);
    }
    // 测试
    @Test
    public void t1() {
        System.out.println(isMobile("12345678901"));
        System.out.println(isMobile("1234567890"));
        // 正确的
        System.out.println(isMobile("13604969873"));
    }
}

image-20240505154936629

7.编写service层

1.UserService.java
package com.sxs.seckill.service;

import com.baomidou.mybatisplus.extension.service.IService;
import com.sxs.seckill.pojo.User;
import com.sxs.seckill.vo.LoginVo;
import com.sxs.seckill.vo.RespBean;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * Description:
 *
 * @Author sun
 * @Create 2024/5/5 15:58
 * @Version 1.0
 */
public interface UserService extends IService<User> {
    /**
     * 用户登录校验
     * @param loginVo
     * @param request
     * @param response
     * @return
     */
    RespBean doLogin(LoginVo loginVo, HttpServletRequest request, HttpServletResponse response);
}

2.UserServiceImpl.java
package com.sxs.seckill.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.sxs.seckill.mapper.UserMapper;
import com.sxs.seckill.pojo.User;
import com.sxs.seckill.service.UserService;
import com.sxs.seckill.utils.MD5Util;
import com.sxs.seckill.utils.ValidatorUtil;
import com.sxs.seckill.vo.LoginVo;
import com.sxs.seckill.vo.RespBean;
import com.sxs.seckill.vo.RespBeanEnum;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * Description:
 *
 * @Author sun
 * @Create 2024/5/5 15:59
 * @Version 1.0
 */
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
    @Resource
    private UserMapper userMapper;

    @Override
    public RespBean doLogin(LoginVo loginVo, HttpServletRequest request, HttpServletResponse response) {
        // 获取用户输入的手机号和密码,此时的密码已经是midPass
        String mobile = loginVo.getMobile();
        String password = loginVo.getPassword();

        // 判断手机号和密码是否为空
        if (StringUtils.isBlank(mobile) || StringUtils.isBlank(password)) {
            return RespBean.error(RespBeanEnum.LOGIN_ERROR);
        }

        // 校验手机号是否正确
        if (!ValidatorUtil.isMobile(mobile)) {
            return RespBean.error(RespBeanEnum.MOBILE_ERROR);
        }

        // 根据手机号查询用户
        User user = userMapper.selectById(mobile);

        // 判断用户是否为空
        if (null == user) {
            return RespBean.error(RespBeanEnum.LOGIN_ERROR);
        }

        // 判断密码是否正确
        if (!MD5Util.midPassToDBPass(password, user.getSlat()).equals(user.getPassword())) {
            return RespBean.error(RespBeanEnum.LOGIN_ERROR);
        }

        // 返回成功
        return RespBean.success();
    }
}

8.编写controller层

1.引入校验的依赖
      <!--validation 参数校验-->
      <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-validation</artifactId>
        <version>2.4.5</version>
      </dependency>
2.LoginController.java
package com.sxs.seckill.controller;

import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

/**
 * Description:
 *
 * @Author sun
 * @Create 2024/5/5 16:41
 * @Version 1.0
 */
@Slf4j
@Controller
@RequestMapping("/login")
public class LoginController {

    /**
     * 访问/login/toLogin会跳转到templates/login.html
     * @return
     */
    @RequestMapping("/toLogin")
    public String toLogin() {
        return "login";
    }
    
}

3.引入静态资源和模板页

image-20240505164717604

4.解析前端登录
1.点击登录,调用login

image-20240505165335357

2.将密码加密加盐之后向后端 /login/doLogin 发送请求

5.测试访问首页
1.首先检查资源是否到了target目录,如果没到需要maven重新编译

image-20240505165614482

2.测试访问 http://localhost:9092/seckill/login/toLogin

image-20240505172622055

6.前端区分多环境
1.可以看到前端请求时使用的/其实只是本机的服务发现,也就是http://localhost:9092/,所以需要区分多环境

image-20240505172723292

2.首先新增一个配置类 GlobalControllerAdvice.java 全局控制器通知,用于向前端传递全局变量
package com.sxs.seckill.config;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ModelAttribute;

/**
 * Description: 全局控制器通知,用于向前端传递全局变量
 *
 * @Author sun
 * @Create 2024/5/5 17:08
 * @Version 1.0
 */
@ControllerAdvice
public class GlobalControllerAdvice {
    // 从配置文件中读取baseUrl,从而使前端可以区分多环境
    @Value("${baseurl}")
    private String baseurl;

    @ModelAttribute("baseUrl")
    public String baseUrl() {
        // 这里可以根据环境变量或其他逻辑来动态确定 URL
        return baseurl;
    }
}

3.在application.yml和application-prod.yml编写baseUrl,区分多环境

image-20240505190742873

4.login.html 读取baseUrl
1.在script标签内添加一行代码使其能够解析Thymeleaf
th:inline="javascript"
2.修改请求,格式为 baseUrl + 资源路径

image-20240505191155843

7.在数据库添加一条记录,可以模拟用户登录
1.假设密码是admin,在前端输出一下第一次加密加盐的结果

image-20240505193323206

image-20240505193407660

2.使用后端的工具类也来加密一下,比对结果,发现结果一致

image-20240505193456039

image-20240505193507376

3.在第二次加密的时候重新设置一个不同的盐为niubi666,模拟不同用户

image-20240505193658984

4.将结果放到数据库中

image-20240505195357038

5.此时的用户名和密码
  • 19588888888:195+八个八
  • admin
8.编写登录的controller并测试
1.LoginController.java
    @ResponseBody
    @RequestMapping("/doLogin")
    public RespBean doLogin(LoginVo loginVo, HttpServletRequest request, HttpServletResponse response) {
        RespBean respBean = userService.doLogin(loginVo, request, response);
        // 返回
        return respBean;
    }

2.测试,登录成功

image-20240505195702856

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1714847.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

5.29_Java程序流程控制

CSDN 同C语言的流程同 1、补充&#xff1a; 1、switch使用时的注意事项 1、表达式只能是byte、short、int、char&#xff0c;JDK5开始支持枚举&#xff0c;JDK7开始支持String、不支持double、float、long switch里面是做分支匹配&#xff0c;也就是可以出现很多分支&am…

【SPSS】基于因子分析法对水果茶调查问卷进行分析

&#x1f935;‍♂️ 个人主页&#xff1a;艾派森的个人主页 ✍&#x1f3fb;作者简介&#xff1a;Python学习者 &#x1f40b; 希望大家多多支持&#xff0c;我们一起进步&#xff01;&#x1f604; 如果文章对你有帮助的话&#xff0c; 欢迎评论 &#x1f4ac;点赞&#x1f4…

【Python】解决Python报错:TypeError: can only concatenate str (not “int“) to str

&#x1f9d1; 博主简介&#xff1a;阿里巴巴嵌入式技术专家&#xff0c;深耕嵌入式人工智能领域&#xff0c;具备多年的嵌入式硬件产品研发管理经验。 &#x1f4d2; 博客介绍&#xff1a;分享嵌入式开发领域的相关知识、经验、思考和感悟&#xff0c;欢迎关注。提供嵌入式方向…

P2341 受欢迎的牛

题目描述 每一头牛的愿望就是变成一头最受欢迎的牛。现在有 N 头牛&#xff0c;给你 M 对整数&#xff0c;表示牛 A 认为牛 B 受欢迎。这种关系是具有传递性的&#xff0c;如果 A 认为 B 受欢迎&#xff0c;B 认为 C 受欢迎&#xff0c;那么牛 A 也认为牛 C 受欢迎。你的任务是…

058.最后一个单词的长度

题意 给你一个字符串 s&#xff0c;由若干单词组成&#xff0c;单词前后用一些空格字符隔开。返回字符串中 最后一个 单词的长度。 单词 是指仅由字母组成、不包含任何空格字符的最大子字符串。 难度 简单 示例 1&#xff1a; 输入&#xff1a;s "Hello World" 输…

开抖店必须要办理营业执照吗?不用营业执照开店的个人店能用吗?

大家好&#xff0c;我是电商花花。 可能大家都发现了&#xff0c;抖音小店个人店不用营业执照&#xff0c;只凭借身份证就能开店。 但是这个个人店花花并不建议大家去开&#xff0c;虽然说用用身份证也能开店&#xff0c;有效的帮我们减少了开店的成本&#xff0c;但是个人店…

2024 angstromCTF re 部分wp

Guess the Flag 附件拖入ida 比较简单&#xff0c;就一个异或 switcher 附件拖入ida 明文flag Polyomino 附件拖入ida 需要输入九个数&#xff0c;然后进入处理和判断&#xff0c;如果满足条件则进入输出flag部分&#xff0c;flag和输入有关&#xff0c;所以要理解需要满足什么…

Ai速递5.29

全球AI新闻速递 1.摩尔线程与无问芯穹合作&#xff0c;实现国产 GPU 端到端 AI 大模型实训。 2.宝马工厂&#xff1a;机器狗上岗&#xff0c;可“嗅探”故障隐患。 3.ChatGPT&#xff1a;macOS 开始公测。 4.Stability AI&#xff1a;推出Stable Assistant&#xff0c;可用S…

GPT-4o:人工智能新纪元的开端

引言 近年来&#xff0c;人工智能领域的发展日新月异&#xff0c;特别是在自然语言处理&#xff08;NLP&#xff09;领域&#xff0c;各种生成预训练模型不断推陈出新。自OpenAI发布GPT-3以来&#xff0c;生成预训练模型在文本生成、语言理解等任务中展现了强大的能力。近期&a…

MVC和MVVM

MVC Model层&#xff1a;用于处理应用程序数据逻辑的部分&#xff0c;通常负责在数据库中存取数据 View&#xff08;视图&#xff09;处理数据显示的部分。通常视图是依据模型数据创建的 Controller&#xff08;控制器&#xff09;是处理用户交互的部分。通常控制器负责从视…

Orange Pi Kunpeng Pro测评

#创作灵感# 参加树莓派鲲鹏开发版的测评活动&#xff0c;也想体验一下该开发版&#xff0c;之前有做过树莓派和香橙派的开发&#xff0c;刚好借此机会了解一下鲲鹏&#xff0c;所以就有了这篇测评文章。 #正文# 引言 说是测评&#xff0c;其实也没有多少测评方面的内容&…

基于jeecgboot-vue3的Flowable新建流程定义(二)

因为这个项目license问题无法开源&#xff0c;更多技术支持与服务请加入我的知识星球。 接上一节 4、编辑好后进行保存&#xff0c;保存代码如下&#xff1a; /*保存流程定义*/const save (data: any) > {//console.log("save data", data); // { process: {..…

装机必备——截图工具Snipaste安装教程

装机必备——截图工具Snipaste安装教程 软件下载 软件名称&#xff1a;Snipaste2.7 软件语言&#xff1a;简体中文 软件大小&#xff1a;15.37M 系统要求&#xff1a;Windows7或更高&#xff0c; 32/64位操作系统 硬件要求&#xff1a;CPU2GHz &#xff0c;RAM2G或更高 下载通…

RAG 高级应用:基于 Nougat、HTML 转换与 GPT-4o 解析复杂 PDF 内嵌表格

一、前言 RAG&#xff08;检索增强生成&#xff09;应用最具挑战性的方面之一是如何处理复杂文档的内容&#xff0c;例如 PDF 文档中的图像和表格&#xff0c;因为这些内容不像传统文本那样容易解析和检索。前面我们有介绍过如何使用 LlamaIndex 提供的 LlamaParse 技术解析复…

重学java51.Collections集合工具类、泛型

"我已不在地坛&#xff0c;地坛在我" —— 《想念地坛》 24.5.28 一、Collections集合工具类 1.概述:集合工具类 2.特点: a.构造私有 b.方法都是静态的 3.使用:类名直接调用 4.方法: static <T> boolean addAll(collection<? super T>c,T... el…

精通推荐算法6:用户行为序列建模 -- 总体架构

1 行为序列建模技术架构 身处目前这个信息爆炸的时代&#xff0c;用户在各推荐场景上有丰富的行为序列。将行为序列特征引入推荐算法中&#xff0c;有利于丰富特征工程体系、获得更立体和更全面的信息&#xff0c;同时可以表达用户兴趣演化过程&#xff0c;并捕获用户实时兴趣…

信号处理中简单实用的方法

最小二乘法拟合消除趋势项 消除趋势项函数 在MATLAB的工具箱中已有消除线性趋势项的detrend函数&#xff1b;再介绍以最小二乘法拟合消除趋势项的polydetrend 函数。 函数:detrend功能:消除线性趋势项 调用格式:ydetrend(x) 说明:输入参数x是带有线性趋势项的信号序列,输出…

OrangePi Kunpeng Pro 开发板测评 | AI 边缘计算 大模型部署

0 前言 此次很幸运能够参与 OrangePi Kunpeng Pro 开发板的测评&#xff0c;感谢 CSDN 给予这次机会。 香橙派联合华为发布了基于昇腾的 OrangePi Kunpeng Pro 开发板&#xff0c;具备 8TOPS 的 AI 算力&#xff0c;能覆盖生态开发板者的主流应用场景&#xff0c;具备完善的配…

这些项目,我当初但凡参与一个,现在也不至于还是个程序员

10年前&#xff0c;我刚开始干开发不久&#xff0c;我觉得这真是一个有前景的职业&#xff0c;我觉得我的未来会无限广阔&#xff0c;我觉得再过几年&#xff0c;我一定工资不菲。于是我开始像很多大佬说的那样&#xff0c;开始制定职业规划&#xff0c;并且坚决执行。但过去这…