0


SpringBoot项目之前后端界面搭建

1.项目搭建

技术点介绍:

前端:Freemarker、jQuery
后端:SpringBoot、MyBatisPlus、Lombok
中间件:Redis

1.1.项目前准备

导入数据库表

用户表:t_user

商品表:t_goods

订单表:t_order

订单项表:t_order_item

数据源表:t_dict_type

数据项表:t_dict_data

** 创建一个springboot项目,注意不要勾选如何组件**

1.2导入pom依赖

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.3.9.RELEASE</version>
    <relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
    <java.version>1.8</java.version>
</properties>
<dependencies>
    <!--freemarker-->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-freemarker</artifactId>
    </dependency>

    <!--spring web-->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

    <!--mysql-->
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <scope>runtime</scope>
        <version>5.1.44</version>
    </dependency>

    <!--lombok-->
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <optional>true</optional>
    </dependency>

    <!--junit-->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
        <exclusions>
            <exclusion>
                <groupId>org.junit.vintage</groupId>
                <artifactId>junit-vintage-engine</artifactId>
            </exclusion>
        </exclusions>
    </dependency>

    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <scope>test</scope>
    </dependency>

    <!-- mybatis plus依赖 -->
    <dependency>
        <groupId>com.baomidou</groupId>
        <artifactId>mybatis-plus-boot-starter</artifactId>
        <version>3.4.0</version>
    </dependency>
    <!-- mybatis-plus-generator依赖 -->
    <dependency>
        <groupId>com.baomidou</groupId>
        <artifactId>mybatis-plus-generator</artifactId>
        <version>3.4.0</version>
    </dependency>

    <!--hariki-->
    <dependency>
        <groupId>com.zaxxer</groupId>
        <artifactId>HikariCP</artifactId>
    </dependency>

    <!-- MD5依赖 -->
    <dependency>
        <groupId>commons-codec</groupId>
        <artifactId>commons-codec</artifactId>
    </dependency>

    <dependency>
        <groupId>org.apache.commons</groupId>
        <artifactId>commons-lang3</artifactId>
        <version>3.6</version>
    </dependency>

    <!-- valid验证依赖 -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-validation</artifactId>
    </dependency>

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

    <!--commons-pool2 对象池依赖 2.0版本的lettuce需要-->
    <dependency>
        <groupId>org.apache.commons</groupId>
        <artifactId>commons-pool2</artifactId>
    </dependency>

    <!--spring-session将session借助于第三方存储(redis/mongodb等等),默认redis-->
    <!--<dependency>
        <groupId>org.springframework.session</groupId>
        <artifactId>spring-session-data-redis</artifactId>
    </dependency>-->
    <dependency>
        <groupId>com.alipay.sdk</groupId>
        <artifactId>alipay-easysdk</artifactId>
        <version>2.0.1</version>
    </dependency>
</dependencies>

<build>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
        </plugin>
    </plugins>
</build>

1.3.转换yml文件

application.yml:

server:
    port: 8081
    servlet:
        context-path: /
spring:
    datasource:
        url: jdbc:mysql://localhost:3306/mybatis_ssm?useSSL=false&useUnicode=true&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=UTC&characterEncoding=UTF8
        driver-class-name: com.mysql.jdbc.Driver
        password: 123456
        username: root
        hikari:
            # 最小空闲连接数量
            minimum-idle: 5
            # 空闲连接存活最大时间,默认600000(10分钟)
            idle-timeout: 180000
            # 连接池最大连接数,默认是10
            maximum-pool-size: 10
            # 此属性控制从池返回的连接的默认自动提交行为,默认值:true
            auto-commit: true
            # 连接池名称
            pool-name: MyHikariCP
            # 此属性控制池中连接的最长生命周期,值0表示无限生命周期,默认1800000即30分钟
            max-lifetime: 1800000
            # 数据库连接超时时间,默认30秒,即30000
            connection-timeout: 30000
    freemarker:
        #设置编码格式
        charset: UTF-8
        #后缀
        suffix:
        #文档类型
        content-type: text/html
        #模板前端
        template-loader-path: classpath:/templates/
        #启用模板
        enabled: true
    mvc:
        static-path-pattern: /static/**
    redis:
       ** #服务端IP
        host: 47.100.191.44
        #端口
        port: 6379
        #密码
        password: (不准看!!!)**
        #选择数据库
        database: 0
        #超时时间
        timeout: 10000ms
        #Lettuce的连接是基于Netty的,连接实例(StatefulRedisConnection)可以在多个线程间并发访问
        #Lettuce线程安全,Jedis线程非安全
        lettuce:
            pool:
                #最大连接数,默认8
                max-active: 8
                #最大连接阻塞等待时间,默认-1
                max-wait: 10000ms
                #最大空闲连接,默认8
                max-idle: 200
                #最小空闲连接,默认0
                min-idle: 5
#mybatis-plus配置
mybatis-plus:
    #所对应的 XML 文件位置
    mapper-locations: classpath*:/mapper/*Mapper.xml
    #别名包扫描路径
    type-aliases-package: com.xbb.spbootpro.model
    configuration:
        #驼峰命名规则
        map-underscore-to-camel-case: true
#日志配置
logging:
    level:

        com.xbb.spbootpro.mapper: debug

**在spbootproApplication.java里面加两个注解辅助 **

** 导入相关文件:如果需要学习请私信我!!!**

1.4.测试

创建一个测试类进行测试:

package com.xbb.spbootpro.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

/**
 * @author冰冰
 * @create  2022-11-08 16:37
 */
@Controller
public class IndexController {
    @RequestMapping("/")
    public String index(){
        return "index.html";
    }
}

先把后台代码跑起来,在访问即可!!

直接访问localhost:8081

如果** **能访问成功说明 项目搭建完成!!!

2.首页功能

2.1.代码生成

导入我们提前准备好的文件夹

打开generator里面的CodeGenerator运行项目

** 生成的代码:**

2.2.前台界面的编写

**IndexController:**
package com.xbb.spbootpro.controller;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.conditions.query.QueryChainWrapper;
import com.xbb.spbootpro.model.Goods;
import com.xbb.spbootpro.service.IGoodsService;
import com.xbb.spbootpro.utils.DataUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;

import java.util.List;
import java.util.Map;

/**
 * @author冰冰
 * @create  2022-11-08 16:37
 */
@Controller
public class IndexController {
    @Autowired
    private IGoodsService goodsService;

    @RequestMapping("/")

    public String index(Model model){
        //摆件花艺
        List<Goods> goods01 = goodsService.list(new QueryWrapper<Goods>()
                .eq("goods_type",01)
                .last("limit 6"));
        //壁挂
        List<Goods> goods07 = goodsService.list(new QueryWrapper<Goods>()
                .eq("goods_type",07)
                .last("limit 12"));
        //为了方便首页数据展示
        DataUtils<Goods> dataUtils = new DataUtils<Goods>();
        Map<String ,List<Goods>> gt01 = dataUtils.transfor(3,goods01);
        Map<String ,List<Goods>> gt07 = dataUtils.transfor(4,goods07);
        model.addAttribute("gt01",gt01);
        model.addAttribute("gt07",gt07);
        return "index.html";
    }
}

index.html:

<!DOCTYPE html>
<html>
   <head lang="en">
      <#include "common/head.html">
      <link rel="stylesheet" type="text/css" href="css/public.css"/>
      <link rel="stylesheet" type="text/css" href="css/index.css" />
   </head>
   <body>
      <!------------------------------head------------------------------>
      <#include "common/top.html">

      <!-------------------------banner--------------------------->
      <div class="block_home_slider">
         <div id="home_slider" class="flexslider">
            <ul class="slides">
               <li>
                  <div class="slide">
                     <img src="img/banner2.jpg"/>
                  </div>
               </li>
               <li>
                  <div class="slide">
                     <img src="img/banner1.jpg"/>
                  </div>
               </li>
            </ul>
         </div>
      </div>
      
      <!------------------------------thImg------------------------------>
      <div class="thImg">
         <div class="clearfix">
            <a href="${ctx}/page/vase_proList.html"><img src="img/i1.jpg"/></a>
            <a href="${ctx}/page/proList.html"><img src="img/i2.jpg"/></a>
            <a href="#2"><img src="img/i3.jpg"/></a>
         </div>
      </div>
      
      <!------------------------------news------------------------------>
      <div class="news">
         < class="wrapper">
            <h2><img src="img/ih1.jpg"/></h2>
            <div class="top clearfix">
               <a href="${ctx}/page/proDetail.html"><img src="img/n1.jpg"/><p></p></a>
               <a href="${ctx}/page/proDetail.html"><img src="img/n2.jpg"/><p></p></a>
               <a href="${ctx}/page/proDetail.html"><img src="img/n3.jpg"/><p></p></a>
            </div>
            <div class="bott clearfix">
               <a href="${ctx}/page/proDetail.html"><img src="img/n4.jpg"/><p></p></a>
               <a href="${ctx}/page/proDetail.html"><img src="img/n5.jpg"/><p></p></a>
               <a href="${ctx}/page/proDetail.html"><img src="img/n6.jpg"/><p></p></a>
            </div>
            <h2><img src="img/ih2.jpg"/></h2>

            <#if gt01?? && gt01?size gt 0>
<#--               遍历gt01中所有的key,是为了该key中的对象-->
               <#list gt01?keys as key>
                  <div class="flower clearfix tran">
                  <#list gt01[key] as g>

                     <a href="proDetail.html" class="clearfix">
                        <dl>
                           <dt>
                              <span class="abl"></span>
                              <img src="${g.goodsImg}"/>
                              <span class="abr"></span>
                           </dt>
                           <dd>${g.goodsName}</dd>
                           <dd><span>¥ ${g.goodsPrice}</span></dd>
                        </dl>
                     </a>
                  </#list>
                  </div>
               </#list>
            </#if>

         </div>
      </div>
      
      <!------------------------------ad------------------------------>
      <a href="#" class="ad"><img src="img/ib1.jpg"/></a>
      
      <!------------------------------people------------------------------>
      <div class="people">
         <div class="wrapper">
            <h2><img src="img/ih3.jpg"/></h2>
            <#if gt07?? && gt07?size gt 0>
            <#list gt07?keys as key>
            <div class="pList clearfix tran">
               <#list gt07[key] as g>
                  <a href="proDetail.html">
                     <dl>
                        <dt>
                           <span class="abl"></span>
                           <img src="${g.goodsImg}"/>
                           <span class="abr"></span>
                        </dt>
                        <dd>${g.goodsName}</dd>
                        <dd><span>¥${g.goodsPrice}</span></dd>
                     </dl>
                  </a>
               </#list>
            </div>
            </#list>
            </#if>
         </div>
      </div>

      <#include "common/footer.html"/>

      <script src="js/public.js" type="text/javascript" charset="utf-8"></script>
      <script src="js/nav.js" type="text/javascript" charset="utf-8"></script>
      <script src="js/jquery.flexslider-min.js" type="text/javascript" charset="utf-8"></script>
      <script type="text/javascript">
         $(function() {
            $('#home_slider').flexslider({
               animation: 'slide',
               controlNav: true,
               directionNav: true,
               animationLoop: true,
               slideshow: true,
               slideshowSpeed:2000,
               useCSS: false
            });

         });
      </script>
   </body>
</html>

注意:要重启服务!!

前台的价格发生的改变

3.用户文明登陆

3.1.实现登陆界面跳转

在controller里面创建一个PageController类

package com.xbb.spbootpro.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;

/**
 * @author冰冰
 * @create  2022-11-09 11:05
 */
@Controller
public class PageController {
    @RequestMapping("/page/{page}")
    private String page(@PathVariable("page") String page){

        return page;

    }

    @RequestMapping("/page/dir/{page}")
    private String page(@PathVariable("dir")String dir
            ,@PathVariable("page") String page){

        return dir +"/"+ page;

    }

}
**重启服务,点击登陆即可跳到登陆界面如下图:**

创建一个login.js:

在login.html里面添加:

在到login.js里面进行测试

刷新项目点击登陆看是否能不能弹出1,能弹1说明这个方法能用。

3.2.登陆验证

部分代码:

**UserDto:**
package com.xbb.spbootpro.model.dto;

import com.xbb.spbootpro.validator.IsMobile;
import lombok.Data;

import javax.validation.constraints.NotBlank;

/**
 * @author冰冰
 * @create  2022-11-10 14:45
 */
@Data
public class UserDto {
    @NotBlank(message = "手机号码不能为空!")
    @IsMobile
    private String mobile;
    @NotBlank(message = "密码不能为空!")
    private String password;
}
**IsMobile:**
package com.xbb.spbootpro.validator;

import javax.validation.Constraint;
import javax.validation.Payload;
import java.lang.annotation.*;

@Documented
@Constraint(
        validatedBy = {MobileValidator.class}
)
@Target({ElementType.METHOD, ElementType.FIELD, ElementType.ANNOTATION_TYPE, ElementType.CONSTRUCTOR, ElementType.PARAMETER, ElementType.TYPE_USE})
@Retention(RetentionPolicy.RUNTIME)
public @interface IsMobile {

    boolean required() default true;

    String message() default "手机号码格式错误!";

    Class<?>[] groups() default {};

    Class<? extends Payload>[] payload() default {};

}
**UserController:**
package com.xbb.spbootpro.controller;

import com.xbb.spbootpro.model.dto.UserDto;
import com.xbb.spbootpro.service.IUserService;
import com.xbb.spbootpro.utils.JsonResponseBody;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;

import org.springframework.web.bind.annotation.RestController;

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

/**
 * <p>
 * 用户信息表 前端控制器
 * </p>
 *
 * @author xbb
 * @since 2022-11-09
 */
@RestController
@RequestMapping("/user")
public class UserController {
    @Autowired
    private IUserService userService;
    @RequestMapping("/toLogin")
    public JsonResponseBody toLogin(@Valid UserDto userDto,
                                    HttpServletRequest req,
                                    HttpServletResponse resp){

        return  userService.toLogin(userDto,req,resp);
    }

}
**UserServiceImpl:**
package com.xbb.spbootpro.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.xbb.spbootpro.exception.BusinessException;
import com.xbb.spbootpro.model.User;
import com.xbb.spbootpro.mapper.UserMapper;
import com.xbb.spbootpro.model.dto.UserDto;
import com.xbb.spbootpro.service.IUserService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xbb.spbootpro.utils.JsonResponseBody;
import com.xbb.spbootpro.utils.JsonResponseStatus;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

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

/**
 * <p>
 * 用户信息表 服务实现类
 * </p>
 *
 * @author xbb
 * @since 2022-11-09
 */
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {
    @Autowired
    private UserMapper userMapper;
    @Override
    public JsonResponseBody toLogin(UserDto userDto, HttpServletRequest req, HttpServletResponse resp) {
//        1.5.1)判断mobile和password是否为空
//        1.5.2)判断mobile格式是否正确
//        1.5.3)根据用户手机号码查询用户是否存在
        User user= userMapper.selectOne(new QueryWrapper<User>().eq("id",userDto.getMobile()));

//        1.5.4)校验账号
        if(user==null){
            throw  new BusinessException(JsonResponseStatus.USER_USERNAME_ERROR);
        }
//        1.5.5)校验密码
        if(userDto.getPassword().equals(user.getPassword())){
            throw new BusinessException(JsonResponseStatus.USER_USERNAME_ERROR);
        }

        return new JsonResponseBody();
    }
}

效果:

什么也不填:

写了正确的手机号:

密码正确,手机号错误

3.3.盐加密

前端加密:防止客户端浏览器F12导致密码泄露

后端加密:防止数据库数据泄露导致密码泄露

后台加密:

**MD5Utils:**
package com.xbb.spbootpro.utils;

import org.apache.commons.codec.digest.DigestUtils;
import org.springframework.stereotype.Component;

import java.util.UUID;

/**
 * MD5加密
 * 用户端:password=MD5(明文+固定Salt)
 * 服务端:password=MD5(用户输入+随机Salt)
 * 用户端MD5加密是为了防止用户密码在网络中明文传输,服务端MD5加密是为了提高密码安全性,双重保险。
 */
@Component
public class MD5Utils {

    //加密盐,与前端一致
    private static String salt="f1g2h3j4";

    /**
     * md5加密
     * @param src
     * @return
     */
    public static String md5(String src){
        return DigestUtils.md5Hex(src);
    }

    /**
     * 获取加密的盐
     * @return
     */
    public static String createSalt(){
        return UUID.randomUUID().toString().replace("-","");
    }

    /**
     * 将前端的明文密码通过MD5加密方式加密成后端服务所需密码
     * 注意:该步骤实际是在前端完成!!!
     * @param inputPass 明文密码
     * @return
     */
    public static String inputPassToFormpass(String inputPass){
        //混淆固定盐salt,安全性更可靠
        String str=salt.charAt(1)+""+salt.charAt(5)+inputPass+salt.charAt(0)+""+salt.charAt(3);
        return md5(str);
    }

    /**
     * 将后端密文密码+随机salt生成数据库的密码
     * @param formPass
     * @param salt
     * @return
     */
    public static String formPassToDbPass(String formPass,String salt){
        //混淆固定盐salt,安全性更可靠
        String str=salt.charAt(7)+""+salt.charAt(4)+formPass+salt.charAt(1)+""+salt.charAt(5);
        return md5(str);
    }

    /**
     * 将用户输入的密码转换成数据库的密码
     * @param inputPass 明文密码
     * @param salt      盐
     * @return
     */
    public static String inputPassToDbPass(String inputPass,String salt){
        String formPass = inputPassToFormpass(inputPass);
        String dbPass = formPassToDbPass(formPass, salt);
        return dbPass;
    }

    public static void main(String[] args) {
        //d7aaa28e3b8e6c88352bd5e7c23829f9
        //5512a78a188b318c074a15f9b056a712
        String formPass = inputPassToFormpass("123456");
        System.out.println("前端加密密码:"+formPass);
        String salt = createSalt();
        System.out.println("后端加密随机盐:"+salt);
        String dbPass = formPassToDbPass(formPass, salt);
        System.out.println("后端加密密码:"+dbPass);
        System.out.println("-------------------------------------------");
        String dbPass1 = inputPassToDbPass("123456", salt);
        System.out.println("最终加密密码:"+dbPass1);
    }
}

前台加密:

login.js:

$(function () {
    alert(6);

    //登陆向后台发送ajax请求
 $("#login").click(function () {
     let mobile =  $("#mobile").val();
     let password =  $("#password").val();

     //1.密码加密
     //1) 定义固定盐
     let salt='f1g2h3j4';
     //2) 固定盐混淆
     let temp=salt.charAt(1)+""+salt.charAt(5)+password+salt.charAt(0)+""+salt.charAt(3);
     //3) 使用MD5完成前端第一次加密
     let pwd=md5(temp);

     $.post("/user/toLogin",{
         mobile:mobile,
         password:password
     },function (res) {
         alert(res.msg)
     },"json");
 });
});
**UserServiceImpl:**
package com.xbb.spbootpro.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.xbb.spbootpro.exception.BusinessException;
import com.xbb.spbootpro.model.User;
import com.xbb.spbootpro.mapper.UserMapper;
import com.xbb.spbootpro.model.dto.UserDto;
import com.xbb.spbootpro.service.IUserService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xbb.spbootpro.utils.JsonResponseBody;
import com.xbb.spbootpro.utils.JsonResponseStatus;
import com.xbb.spbootpro.utils.MD5Utils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

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

/**
 * <p>
 * 用户信息表 服务实现类
 * </p>
 *
 * @author xbb
 * @since 2022-11-09
 */
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {
    @Autowired
    private UserMapper userMapper;
    @Override
    public JsonResponseBody toLogin(UserDto userDto, HttpServletRequest req, HttpServletResponse resp) {
//        1.5.1)判断mobile和password是否为空
//        1.5.2)判断mobile格式是否正确
//        1.5.3)根据用户手机号码查询用户是否存在
        User user= userMapper.selectOne(new QueryWrapper<User>().eq("id",userDto.getMobile()));

//        1.5.4)校验账号
        if(user==null){
            throw  new BusinessException(JsonResponseStatus.USER_USERNAME_ERROR);
        }
        //前台传递到后台的密码,要进过工具类md5加密一次,才有可能跟数据库密码匹配上
     String pwd = MD5Utils.formPassToDbPass(userDto.getPassword(),user.getSalt());
//        1.5.5)校验密码
        if(!pwd.equals(user.getPassword())){
            throw new BusinessException(JsonResponseStatus.USER_USERNAME_ERROR);
        }

        return new JsonResponseBody();
    }
}

4.服务端和客户端登陆密码管理

UserServiceImpl.java变更如下

package com.xbb.spbootpro.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.xbb.spbootpro.exception.BusinessException;
import com.xbb.spbootpro.model.User;
import com.xbb.spbootpro.mapper.UserMapper;
import com.xbb.spbootpro.model.dto.UserDto;
import com.xbb.spbootpro.service.IRedisService;
import com.xbb.spbootpro.service.IUserService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xbb.spbootpro.utils.CookieUtils;
import com.xbb.spbootpro.utils.JsonResponseBody;
import com.xbb.spbootpro.utils.JsonResponseStatus;
import com.xbb.spbootpro.utils.MD5Utils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.UUID;

/**
 * <p>
 * 用户信息表 服务实现类
 * </p>
 *
 * @author xbb
 * @since 2022-11-09
 */
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private IRedisService iRedisService;
    @Override
    public JsonResponseBody toLogin(UserDto userDto, HttpServletRequest req, HttpServletResponse resp) {
//        1.5.1)判断mobile和password是否为空
//        1.5.2)判断mobile格式是否正确
//        1.5.3)根据用户手机号码查询用户是否存在
        User user= userMapper.selectOne(new QueryWrapper<User>().eq("id",userDto.getMobile()));

//        1.5.4)校验账号
        if(user==null){
            throw  new BusinessException(JsonResponseStatus.USER_USERNAME_ERROR);
        }
        //前台传递到后台的密码,要进过工具类md5加密一次,才有可能跟数据库密码匹配上
        String pwd = MD5Utils.formPassToDbPass(userDto.getPassword(),user.getSalt());
//        1.5.5)校验密码
        if(!pwd.equals(user.getPassword())){
            throw new BusinessException(JsonResponseStatus.USER_USERNAME_ERROR);
        }

        //6.将登陆用户对象与token令牌进行绑定保存到cookie和redis
        //创建登陆令牌token
        String token= UUID.randomUUID().toString().replace("-","");
        //将token令牌保存到cookie中
        CookieUtils.setCookie(req,resp,"token",token,7200);
        //将登陆token令牌与用户对象user绑定到redis中
        iRedisService.setUserToRedis(token,user);
        //将用户登陆的昵称设置到cookie中
        CookieUtils.setCookie(req,resp,"nickname",user.getNickname());
        return new JsonResponseBody<>();
    }
}
IRedisService.java
package com.xbb.spbootpro.service;

import com.xbb.spbootpro.model.User;

/**
 * @author冰冰
 * @create  2022-11-10 16:39
 */
public interface IRedisService {
    void setUserToRedis(String token, User user);

    User getUserByToken(String token);
}
RedisServiceImpl:
package com.xbb.spbootpro.service.impl;

import com.xbb.spbootpro.model.User;
import com.xbb.spbootpro.service.IRedisService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

/**
 * @author冰冰
 * @create  2022-11-10 16:43
 */

@Service
public class RedisServiceImpl implements IRedisService {

    @Autowired
    private RedisTemplate<String,Object> redisTemplate;

    @Override
    public void setUserToRedis(String token, User user) {
        redisTemplate.opsForValue().set("user:"+token,user,7200L);
    }

    @Override
    public User getUserByToken(String token) {
        return (User) redisTemplate.opsForValue().get("user:"+token);
    }
}
标签: spring boot java spring

本文转载自: https://blog.csdn.net/m0_68211831/article/details/127750313
版权归原作者 冰冰酱哈 所有, 如有侵权,请联系我们删除。

“SpringBoot项目之前后端界面搭建”的评论:

还没有评论