ylb-接口8手机号注册

news2024/11/27 0:27:07

总览:
在这里插入图片描述
在web模块下的service包,补充短信接口(SmsService):检查用户发送的验证码是否正确

package com.bjpowernode.front.service;

public interface SmsService {
    /**
     * @param phone 手机号
     * @return true:发送成功,false 其他情况
     */
    boolean sendSms(String phone);

    /**
     * @param phone 手机号
     * @param code  提交参数中的验证码
     * @return
     */
    boolean checkSmsCode(String phone,String code);
}

实现这个接口还没有实现的方法,在SmsCodeRegisterImpl添加,验证客户端接受到短信验证码是否正确:

package com.bjpowernode.front.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.bjpowernode.common.constants.RedisKey;
import com.bjpowernode.front.config.JdwxSmsConfig;
import com.bjpowernode.front.service.SmsService;
import org.apache.commons.lang3.RandomStringUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpStatus;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.util.concurrent.TimeUnit;

/**
 * 注册发送短信验证码
 */

@Service(value = "smsCodeRegisterImpl")
public class SmsCodeRegisterImpl implements SmsService {

    @Resource
    private StringRedisTemplate stringRedisTemplate;

    @Resource
    private JdwxSmsConfig smsConfig;

    @Override
    public boolean sendSms(String phone) {
        boolean send = false;
        // 设置短信内容
        String random  = RandomStringUtils.randomNumeric(4);
        System.out.println("注册验证码的随机数 random="+random);
        //更新content中的  %s   【大富科技】你的验证码是:%s,3分钟内有效,请勿泄露给他人
        String content  = String.format(smsConfig.getContent(), random);

        //使用HttpClient发送 get 请求给第三方。
        CloseableHttpClient client = HttpClients.createDefault();
        //https://way.jd.com/chuangxin/dxjk?mobile=13568813957&content=
        //【创信】你的验证码是:5873,3分钟内有效!&appkey=您申请的APPKEY
        String url = smsConfig.getUrl()+"?mobile="+phone
                        +"&content=" + content
                        +"&appkey="+smsConfig.getAppkey();
        HttpGet get  = new HttpGet(url);

        try{
            CloseableHttpResponse response = client.execute(get);
            if( response.getStatusLine().getStatusCode() == HttpStatus.SC_OK ){
                //得到返回的数据,json
                String text = EntityUtils.toString(response.getEntity());
                
                //解析json
                if(StringUtils.isNotBlank(text)){
                    // fastjson
                    JSONObject jsonObject = JSONObject.parseObject(text);
                    if("10000".equals(jsonObject.getString("code"))){ //第三方接口调用成功
                        //读取result中的key:ReturnStatus
                        if("Success".equalsIgnoreCase(
                                jsonObject.getJSONObject("result").getString("ReturnStatus"))){
                            //短信发送成功
                            send  = true;

                            //把短信验证码,存到redis
                            String key = RedisKey.KEY_SMS_CODE_REG + phone;
                            stringRedisTemplate.boundValueOps(key).set(random,3 , TimeUnit.MINUTES);

                        }
                    }
                }
            }
        }catch (Exception e){
            e.printStackTrace();
        }
        return send;
    }

    @Override
    public boolean checkSmsCode(String phone, String code) {
        String key = RedisKey.KEY_SMS_CODE_REG + phone;
        if( stringRedisTemplate.hasKey(key)){
            String querySmsCode = stringRedisTemplate.boundValueOps(key).get();
            if( code.equals(querySmsCode)){  // 输入的验证码和redis里相应的验证码是否相等
                return true;
            }
        }
        return false;
    }

}

在api模块下的service包,补充用户接口(UserService):用户注册

package com.bjpowernode.api.service;

import com.bjpowernode.api.model.User;
import com.bjpowernode.api.pojo.UserAccountInfo;

public interface UserService {

    /**
     * 根据手机号查询数据
     */
    User queryByPhone(String phone);

    /*用户注册*/
    int userRegister(String phone, String password);

    /*登录*/
    User userLogin(String phone, String pword);

    /*更新实名认证信息*/
    boolean modifyRealname(String phone, String name, String idCard);

    /*获取用户和资金信息*/
    UserAccountInfo queryUserAllInfo(Integer uid);

    /*查询用户*/
    User queryById(Integer uid);
}

实现这个接口方法,在dataservice模块service包下,补充UserServiceImpl,用户注册:
1、检查参数(电话是否标准,密码是否标准)
2、判断注册手机号是否已经注册过
3、md5密码加密
4、注册用户(向user数据表添加数据)
5、获取用户主键值(编写相应的mapper)
6、判断

package com.bjpowernode.dataservice.service;

import com.bjpowernode.api.model.FinanceAccount;
import com.bjpowernode.api.model.User;
import com.bjpowernode.api.pojo.UserAccountInfo;
import com.bjpowernode.api.service.UserService;
import com.bjpowernode.common.util.CommonUtil;
import com.bjpowernode.dataservice.mapper.FinanceAccountMapper;
import com.bjpowernode.dataservice.mapper.UserMapper;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.config.annotation.DubboService;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.Date;

@DubboService(interfaceClass = UserService.class,version = "1.0")
public class UserServiceImpl implements UserService {

    @Resource
    private UserMapper userMapper;

    @Resource
    private FinanceAccountMapper financeAccountMapper;

    @Value("${ylb.config.password-salt}")
    private String passwordSalt;

    @Override
    public User queryByPhone(String phone) {
        User user = null;
        if(CommonUtil.checkPhone(phone)){
            user = userMapper.selectByPhone(phone);
        }
        return user;
    }

    /*用户注册*/
    @Transactional(rollbackFor = Exception.class)  // 开启事务
    @Override
    public synchronized int userRegister(String phone, String password) { // synchronized:同步的方法,保证线程安全,该方法处理时,其他方法不能对其参数二次处理(phone和password)
        int result = 0;//默认参数不正确
        if( CommonUtil.checkPhone(phone)
                && (password != null && password.length()==32)){

            //判断手机号在库中是否存在
            User queryUser = userMapper.selectByPhone(phone);
            if(queryUser == null){
                //注册密码的md5二次加密。 给原始的密码加盐(salt)
                String newPassword = DigestUtils.md5Hex( password + passwordSalt);

                //注册u_user
                User user = new User();
                user.setPhone(phone);
                user.setLoginPassword(newPassword);
                user.setAddTime(new Date());
                userMapper.insertReturnPrimaryKey(user);

                //获取主键user.getId()
                FinanceAccount account = new FinanceAccount();
                account.setUid(user.getId());
                account.setAvailableMoney(new BigDecimal("0"));
                financeAccountMapper.insertSelective(account);

                //成功result = 1
                result = 1;
            } else {
                //手机号存在
                result = 2;
            }
        }
        return result;
    }

    /*登录*/
    @Transactional(rollbackFor = Exception.class)
    @Override
    public User userLogin(String phone, String password) {

        User user = null;
        if( CommonUtil.checkPhone(phone) && (password != null && password.length() == 32)) {
            String newPassword = DigestUtils.md5Hex( password + passwordSalt);
            user = userMapper.selectLogin(phone,newPassword);
            //更新最后登录时间
            if( user != null){
                user.setLastLoginTime(new Date());
                userMapper.updateByPrimaryKeySelective(user);
            }
        }
        return user;
    }

    /*更新实名认证信息*/
    @Override
    public boolean modifyRealname(String phone, String name, String idCard) {
        int rows = 0;
        if(!StringUtils.isAnyBlank(phone,name,idCard)){
             rows  = userMapper.updateRealname(phone,name,idCard);
        }
        return rows > 0 ;
    }

    /*获取用户和资金信息*/
    @Override
    public UserAccountInfo queryUserAllInfo(Integer uid) {
        UserAccountInfo info = null;
        if( uid != null && uid > 0 ) {
            info  = userMapper.selectUserAccountById(uid);
        }
        return info ;
    }

    /*查询用户*/
    @Override
    public User queryById(Integer uid) {
        User user = null;
        if( uid != null && uid > 0 ){
            user = userMapper.selectByPrimaryKey(uid);
        }
        return user;
    }
}

其中:
1、md5加密需要在dataservice模块下resources/application.yml,添加配置信息:

#密码的盐
ylb:
  config:
    password-salt: fiwsyhrf9wejroi2huio3y4234operw3

2、添加记录,获取主键值(需要在dataservice模块mapper包下的UserMapper接口添加方法,并在resources/mappers/UserMapper.xml编写SQL语句):

    /*添加记录,获取主键值*/
    int insertReturnPrimaryKey(User user);
<!--添加记录,获取主键值-->
  <insert id="insertReturnPrimaryKey">
    insert into u_user(phone, login_password,add_time)
    values(#{phone},#{loginPassword},#{addTime})

    <selectKey keyColumn="newId" keyProperty="id" resultType="int" order="AFTER">
       select LAST_INSERT_ID() as newId
    </selectKey>
  </insert>

手机号注册属于“用户功能”,所以在web模块的usercontroller类下添加:

package com.bjpowernode.front.controller;

import com.bjpowernode.api.model.User;
import com.bjpowernode.api.pojo.UserAccountInfo;
import com.bjpowernode.common.enums.RCode;
import com.bjpowernode.common.util.CommonUtil;
import com.bjpowernode.common.util.JwtUtil;
import com.bjpowernode.front.service.RealnameServiceImpl;
import com.bjpowernode.front.service.SmsService;
import com.bjpowernode.front.view.RespResult;
import com.bjpowernode.front.vo.RealnameVO;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation;
import io.swagger.models.auth.In;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.apache.jute.compiler.generated.Rcc;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.management.relation.Relation;
import java.util.HashMap;
import java.util.Map;

@Api(tags = "用户功能")
@RestController
@RequestMapping("/v1/user")
public class UserController extends BaseController {

    @Resource(name = "smsCodeRegisterImpl")
    private SmsService smsService;

    @Resource(name = "smsCodeLoginImpl")
    private SmsService loginSmsService;

    @Resource
    private RealnameServiceImpl realnameService;

    @Resource
    private JwtUtil jwtUtil;

    /**手机号注册用户*/
    @ApiOperation(value = "手机号注册用户")
    @PostMapping("/register")
    public RespResult userRegister(@RequestParam String phone,
                                   @RequestParam String pword,
                                   @RequestParam String scode){
        RespResult result = RespResult.fail();
        //1.检查参数
        if( CommonUtil.checkPhone(phone)){
            if(pword !=null && pword.length() == 32 ){
                //检查短信验证码
                if( smsService.checkSmsCode(phone,scode)){
                    //可以注册
                    int registerResult  = userService.userRegister(phone,pword);
                    if( registerResult == 1 ){
                        result = RespResult.ok();
                    } else if( registerResult == 2 ){
                        result.setRCode(RCode.PHONE_EXISTS);
                    } else {
                        result.setRCode(RCode.REQUEST_PARAM_ERR);
                    }
                } else {
                    //短信验证码无效
                    result.setRCode(RCode.SMS_CODE_INVALID);
                }
            } else {
                result.setRCode(RCode.REQUEST_PARAM_ERR);
            }
        } else {
            //手机号格式不正确
            result.setRCode(RCode.PHONE_FORMAT_ERR);
        }
        return result;
    }

    /** 手机号是否存在 */
    @ApiOperation(value = "手机号是否注册过",notes = "在注册功能中,判断手机号是否可以注册")
    @ApiImplicitParam(name = "phone",value = "手机号")
    @GetMapping("/phone/exists")
    public RespResult phoneExists(@RequestParam("phone") String phone){
        RespResult result  = new RespResult();
        result.setRCode(RCode.PHONE_EXISTS);

        //1.检查请求参数是否符合要求
        if(CommonUtil.checkPhone(phone)){
            //可以执行逻辑 ,查询数据库,调用数据服务
            User user = userService.queryByPhone(phone);
            if( user == null ){
                //可以注册
                result = RespResult.ok();
            }
            //把查询到的手机号放入redis。 然后检查手机号是否存在,可以查询redis
        } else {
            result.setRCode(RCode.PHONE_FORMAT_ERR);
        }
        return result;
    }


    /** 登录,获取token-jwt*/
    @ApiOperation(value = "用户登录-获取访问token")
    @PostMapping("/login")
    public RespResult userLogin(@RequestParam String phone,
                                @RequestParam String pword,
                                @RequestParam String scode) throws Exception{
        RespResult result = RespResult.fail();
        if(CommonUtil.checkPhone(phone) && (pword != null && pword.length() == 32) ){
            if(loginSmsService.checkSmsCode(phone,scode)){
                //访问data-service
                User user = userService.userLogin(phone,pword);
                if( user != null){
                    //登录成功,生成token
                    Map<String, Object> data = new HashMap<>();
                    data.put("uid",user.getId());
                    String jwtToken = jwtUtil.createJwt(data,120);

                    result = RespResult.ok();
                    result.setAccessToken(jwtToken);

                    Map<String,Object> userInfo = new HashMap<>();
                    userInfo.put("uid",user.getId());
                    userInfo.put("phone",user.getPhone());
                    userInfo.put("name",user.getName());
                    result.setData(userInfo);
                } else {
                    result.setRCode(RCode.PHONE_LOGIN_PASSWORD_INVALID);
                }
            } else {
                result.setRCode(RCode.SMS_CODE_INVALID);
            }
        } else {
            result.setRCode(RCode.REQUEST_PARAM_ERR);
        }


        return result;
    }


    /** 实名认证  vo: value object*/
    @ApiOperation(value = "实名认证",notes = "提供手机号和姓名,身份证号。 认证姓名和身份证号是否一致")
    @PostMapping("/realname")
    public RespResult userRealname(@RequestBody RealnameVO realnameVO){
        RespResult result = RespResult.fail();
        result.setRCode(RCode.REQUEST_PARAM_ERR);
        //1验证请求参数
        if( CommonUtil.checkPhone(realnameVO.getPhone())){
            if(StringUtils.isNotBlank(realnameVO.getName()) &&
                    StringUtils.isNotBlank(realnameVO.getIdCard())){

                //判断用户已经做过
                User user = userService.queryByPhone(realnameVO.getPhone());
                if( user != null ){
                    if( StringUtils.isNotBlank(user.getName())){
                        result.setRCode(RCode.REALNAME_RETRY);
                    } else {
                        //有短信验证码,先不写
                        //调用第三方接口,判断认证结果
                        boolean realnameResult  = realnameService.handleRealname(
                                realnameVO.getPhone(),realnameVO.getName(),
                                realnameVO.getIdCard());
                        if( realnameResult == true ){
                            result = RespResult.ok();
                        } else {
                            result.setRCode(RCode.REALNAME_FAIL);
                        }
                    }
                }
            }
        }
        return result;
    }


    /** 用户中心 */
    @ApiOperation(value = "用户中心")
    @GetMapping("/usercenter")
    public RespResult userCenter(@RequestHeader(value = "uid",required = false) Integer uid){
        RespResult result  = RespResult.fail();
        if( uid != null && uid > 0 ){
            UserAccountInfo userAccountInfo = userService.queryUserAllInfo(uid);
            if( userAccountInfo != null ){
                result = RespResult.ok();

                Map<String,Object> data = new HashMap<>();
                data.put("name",userAccountInfo.getName());
                data.put("phone",userAccountInfo.getPhone());
                data.put("headerUrl",userAccountInfo.getHeaderImage());
                data.put("money",userAccountInfo.getAvailableMoney());
                if( userAccountInfo.getLastLoginTime() != null){
                    data.put("loginTime", DateFormatUtils.format(
                            userAccountInfo.getLastLoginTime(),"yyyy-MM-dd HH:mm:ss"));
                } else  {
                    data.put("loginTime","-");
                }
                result.setData(data);

            }
        }


        return result;

    }
}

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

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

相关文章

聚集十二罗汉,探索宇宙本质,马斯克神秘的xAI

作者 | 德新编辑 | 王博 马斯克组团入局通用人工智能。 7月12日&#xff0c;马斯克发推官宣成立新的公司xAI。据官网介绍&#xff0c;这是一家试图「探索理解宇宙本质」的公司。 新公司公布了12名首批成员&#xff0c;除了马斯克外&#xff0c;他们曾经在「AlphaStar、AlphaCod…

springboot线上买菜系统

开发语言&#xff1a;Java 框架&#xff1a;springboot JDK版本&#xff1a;JDK1.8 服务器&#xff1a;tomcat7 数据库&#xff1a;mysql 5.7&#xff08;一定要5.7版本&#xff09; 数据库工具&#xff1a;Navicat11 开发软件&#xff1a;eclipse/myeclipse/idea Maven…

【Linux进阶之路】冯诺依曼体系结构与操作系统

前言 存储器与CPU 在正式介绍今天的话题之前&#xff0c;博主先来带大家搞清楚一些硬件的概念&#xff0c;方便接下来的理解。 存储器&#xff0c;顾名思义就是用来存储的设备&#xff0c;那在计算机里&#xff0c;存储器包含什么呢&#xff1f; 答&#xff1a;内存 外存&a…

【C语言初阶(14)】扫雷游戏(优化:标记地雷+自动展开)

文章目录 Ⅰ游戏规则Ⅱ 游戏实现思路Ⅲ 游戏实现步骤⒈菜单界面⒉创建棋盘① 创建两个棋盘② 防止数组越界 ⒊棋盘初始化⒋棋盘的打印⒌布置地雷⒍玩家排查雷实现步骤⒎计算 x&#xff0c;y 周围有多少雷⒏展开非雷区⒐标记地雷⒑取消标记 Ⅳ 模块化代码实现⒈test.c⒉game.h⒊…

TCP协议下的三大协议的验证实验

系列文章目录 数通王国历险记&#xff08;1&#xff09; 前言 一&#xff0c;我们要先知道PDU是什么&#xff1f; 二、TCP协议下的三大协议的验证实验 1.FTP的验证实验 1&#xff0c;拓扑图 2.将lsw4配置一下 3&#xff0c;FTP服务器端开启FTP服务&#xff1a; 4&#x…

Jenkins的几种安装方式以及邮件配置

目录 Jenkins介绍 Jenkins下载、安装 一、通过war包安装 二、通过docker安装 jenkins 容器中添加 git, maven 等组件 jenkins 容器中的公钥私钥 在 jenkins 容器中调用 docker 简单的方式启动 Docker server REST API 一个 jenkins 示例 三、通过Homebrew安装 访问Je…

静态库 的制作与使用

文章目录 重要命令程序组成静态库制作流程静态库的使用 gcc main.c -o APP -I(i) 头文件路径 -l(L) 库名字&#xff08;xxx) -L 库路径 重要命令 gcc -o -I(大写i) -l(小写L) -L cp&#xff1a;复制文件 -r 递归&#xff0c;用于复制文件夹所有文件 mv&#xff1a;移动文件 程…

代码随想录算法训练营第53天 | 动态规划 part14 ● 1143.最长公共子序列 ●1035.不相交的线 ● 53. 最大子序和

# 1143.最长公共子序列 和718最长公共子数组 对比 本题可以不连续 int longestCommonSubsequence(string text1, string text2) {vector<vector<int>> dp(text1.size() 1, vector<int>(text2.size() 1, 0));for (int i 1; i < text1.size(); i) {for…

陆地生态系统植被净初级生产力(NPP)—CASA模型

由于全球变暖、大气中温室气体浓度逐年增加等问题的出现&#xff0c;“双碳”行动特别是碳中和已经在世界范围形成广泛影响。碳中和可以从碳排放&#xff08;碳源&#xff09;和碳固定&#xff08;碳汇&#xff09;这两个侧面来理解。陆地生态系统在全球碳循环过程中有着重要作…

Swagger、knife4j简介

Swagger 简介 Swagger 是一个规范和完整的框架&#xff0c;用于生成、描述、调用和可视化 RESTful 风格的 Web 服务(API Documentation & Design Tools for Teams | Swagger)。 它的主要作用是&#xff1a; 使得前后端分离开发更加方便&#xff0c;有利于团队协作 接口的…

leetcode 1218. Longest Arithmetic Subsequence of Given Difference(给定差值的最长算术子序列)

给数组arr和一个差值difference, 不打乱arr中数字的顺序&#xff0c;抽取最长的子序列&#xff0c;使序列中每相邻两个元素的差值为difference. 求满足条件的最长子序列的长度。 思路&#xff1a; DP 因为差值difference是固定的&#xff0c;每抽取一个元素&#xff0c;它前…

帆软报表分页预览如何增加一种新的导出类型。

如图,这里要在 导出下拉菜单中新增一个签章PDF的导出。 通过分析源码,发现这个菜单的定义是再报表预览加载的html页面里面 咋们如何再这里面插入我们新加的菜单项呢。 首先该页面的内容是通过MemXPageActor的flushHtml方法产生的。所以我们需要继承MemXPageActor来重载flus…

ios h5底部安全区适配

相信在ios 移动端开发h5前端童鞋 肯定会知道 就是 很多ios款型的手机 底部有一条黑色的杠杠 或者白色哎 就是会遮挡一部分我们的元素 特别是底部需要悬浮一些按钮的时候 这个就是ios的底部安全区域 对应的还有顶部的哈 这里就说下 底部的 <meta name"viewport"…

在Linux中使用curl访问EasyCVR页面,返回报错Unauthorized是什么原因?

EasyCVR可拓展性强、视频能力灵活、部署轻快&#xff0c;可支持的主流标准协议有国标GB28181、RTSP/Onvif、RTMP等&#xff0c;以及支持厂家私有协议与SDK接入&#xff0c;包括海康Ehome、海大宇等设备的SDK等。平台既具备传统安防视频监控的能力&#xff0c;比如&#xff1a;视…

第四章 数学知识(四)——容斥原理与博弈论

文章目录 容斥原理博弈论SG函数 容斥原理练习题890. 能被整除的数 博弈论练习题891. Nim游戏893. 集合-Nim游戏892. 台阶-Nim游戏894. 拆分-Nim游戏 容斥原理 若干个相交集合&#xff0c;它们的并集中存在多少个元素&#xff1f; 假设n为所有集合的元素个数相加&#xff0c;因…

vue img 图片损坏时展示替图片

场景&#xff1a;图片地址找不到时&#xff0c;会展示如图一&#xff1b;虽然没什么大影响&#xff0c;但是有点丑&#xff0c;需求是想在图片损坏时展示替补图片&#xff0c;如图二。 代码实现&#xff1a;给img标签加error事件 <img :src"item.imageUrl" :alt&q…

android JSBridge的加载时机问题

https://github.com/lzyzsd/JsBridge 也算是比较悠久和使用了。 可供参考的android和IOS&#xff0c;以及前端的使用 https://segmentfault.com/a/1190000018208609 遇到的问题&#xff1a; 比如&#xff1a; 从前端在加载WebView的时候&#xff0c;执行了某些动作&#xff0c…

【Java/大数据】Kafka简介

Kafka简介 Kafka概念关键功能应用场景 Kafka的原理Kafka 的消息模型早期的队列模型发布-订阅模型Producer、Consumer、Broker、Topic、PartitionPartitionoffsetISR Consumer Groupleader选举Controller leaderPartition leader producer 的写入流程 多副本机制replicas的同步时…

介绍AI绘画课,让智能工具助力创作 释放无限想象力 助你成为绘画大师

演示地址&#xff1a; www.runruncode.com/portal/article/index/id/19458/cid/81.html 画画是一项有趣的活动&#xff0c;它让人充满无限可能。对许多人来说&#xff0c;画画既是一种放松的方式&#xff0c;也是一种与创意、文化和艺术联系的途径。如果你是一个初学者&#x…

《深度学习推荐系统》笔记

目录 一、推荐系统是什么1.作用和意义2.推荐系统的架构2.1 逻辑架构2.2 技术架构 二、传统的推荐系统方法1. 协同过滤算法1.1 userCF&&ItemCF1.3 矩阵分解算法 2. 逻辑回归算法3. 因子分解机3.1 POLY2模型3.2 FM模型3.3 FFM模型3.4 小结 4. 组合模型4.1 GBDTLR组合模型…