• SpringBoot项目之前后端界面搭建


    目录

    1.项目搭建

    1.1.项目前准备

    1.2导入pom依赖

    1.3.转换yml文件

    1.4.测试

    2.首页功能

    2.1.代码生成

     2.2.前台界面的编写

    3.用户文明登陆

    3.1.实现登陆界面跳转

     3.2.登陆验证

    3.3.盐加密

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


    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依赖

    
        org.springframework.boot
        spring-boot-starter-parent
        2.3.9.RELEASE
         
    

    
        1.8
    
    
        
        
            org.springframework.boot
            spring-boot-starter-freemarker
        
    
        
        
            org.springframework.boot
            spring-boot-starter-web
        
    
        
        
            mysql
            mysql-connector-java
            runtime
            5.1.44
        
    
        
        
            org.projectlombok
            lombok
            true
        
    
        
        
            org.springframework.boot
            spring-boot-starter-test
            test
            
                
                    org.junit.vintage
                    junit-vintage-engine
                
            
        
    
        
            junit
            junit
            test
        
    
        
        
            com.baomidou
            mybatis-plus-boot-starter
            3.4.0
        
        
        
            com.baomidou
            mybatis-plus-generator
            3.4.0
        
    
        
        
            com.zaxxer
            HikariCP
        
    
        
        
            commons-codec
            commons-codec
        
    
        
            org.apache.commons
            commons-lang3
            3.6
        
    
        
        
            org.springframework.boot
            spring-boot-starter-validation
        
    
        
        
            org.springframework.boot
            spring-boot-starter-data-redis
        
    
        
        
            org.apache.commons
            commons-pool2
        
    
        
        
        
            com.alipay.sdk
            alipay-easysdk
            2.0.1
        
    
    
    
        
            
                org.springframework.boot
                spring-boot-maven-plugin
            
        
    

    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.测试

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

    1. package com.xbb.spbootpro.controller;
    2. import org.springframework.stereotype.Controller;
    3. import org.springframework.web.bind.annotation.RequestMapping;
    4. /**
    5. * @author冰冰
    6. * @create  2022-11-08 16:37
    7. */
    8. @Controller
    9. public class IndexController {
    10. @RequestMapping("/")
    11. public String index(){
    12. return "index.html";
    13. }
    14. }

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

    直接访问localhost:8081

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

    2.首页功能

    2.1.代码生成

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

     打开generator里面的CodeGenerator运行项目

     生成的代码:

     2.2.前台界面的编写

    IndexController:
    1. package com.xbb.spbootpro.controller;
    2. import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
    3. import com.baomidou.mybatisplus.extension.conditions.query.QueryChainWrapper;
    4. import com.xbb.spbootpro.model.Goods;
    5. import com.xbb.spbootpro.service.IGoodsService;
    6. import com.xbb.spbootpro.utils.DataUtils;
    7. import org.springframework.beans.factory.annotation.Autowired;
    8. import org.springframework.stereotype.Controller;
    9. import org.springframework.ui.Model;
    10. import org.springframework.web.bind.annotation.RequestMapping;
    11. import java.util.List;
    12. import java.util.Map;
    13. /**
    14. * @author冰冰
    15. * @create  2022-11-08 16:37
    16. */
    17. @Controller
    18. public class IndexController {
    19. @Autowired
    20. private IGoodsService goodsService;
    21. @RequestMapping("/")
    22. public String index(Model model){
    23. //摆件花艺
    24. List goods01 = goodsService.list(new QueryWrapper()
    25. .eq("goods_type",01)
    26. .last("limit 6"));
    27. //壁挂
    28. List goods07 = goodsService.list(new QueryWrapper()
    29. .eq("goods_type",07)
    30. .last("limit 12"));
    31. //为了方便首页数据展示
    32. DataUtils dataUtils = new DataUtils();
    33. Map> gt01 = dataUtils.transfor(3,goods01);
    34. Map> gt07 = dataUtils.transfor(4,goods07);
    35. model.addAttribute("gt01",gt01);
    36. model.addAttribute("gt07",gt07);
    37. return "index.html";
    38. }
    39. }

    index.html:

    
    
       
          <#include "common/head.html">
          
          
       
       
          
          <#include "common/top.html">
    
          
          
    < class="wrapper">

    <#if gt01?? && gt01?size gt 0> <#-- 遍历gt01中所有的key,是为了该key中的对象--> <#list gt01?keys as key>

    <#if gt07?? && gt07?size gt 0> <#list gt07?keys as key>
    <#include "common/footer.html"/>

    注意:要重启服务!!

    前台的价格发生的改变

    3.用户文明登陆

    3.1.实现登陆界面跳转

    在controller里面创建一个PageController类

    1. package com.xbb.spbootpro.controller;
    2. import org.springframework.stereotype.Controller;
    3. import org.springframework.web.bind.annotation.PathVariable;
    4. import org.springframework.web.bind.annotation.RequestMapping;
    5. /**
    6. * @author冰冰
    7. * @create  2022-11-09 11:05
    8. */
    9. @Controller
    10. public class PageController {
    11. @RequestMapping("/page/{page}")
    12. private String page(@PathVariable("page") String page){
    13. return page;
    14. }
    15. @RequestMapping("/page/dir/{page}")
    16. private String page(@PathVariable("dir")String dir
    17. ,@PathVariable("page") String page){
    18. return dir +"/"+ page;
    19. }
    20. }
    重启服务,点击登陆即可跳到登陆界面如下图:
    

    创建一个login.js:

     在login.html里面添加:

     在到login.js里面进行测试

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

     3.2.登陆验证


    部分代码:

    UserDto:
    1. package com.xbb.spbootpro.model.dto;
    2. import com.xbb.spbootpro.validator.IsMobile;
    3. import lombok.Data;
    4. import javax.validation.constraints.NotBlank;
    5. /**
    6. * @author冰冰
    7. * @create  2022-11-10 14:45
    8. */
    9. @Data
    10. public class UserDto {
    11. @NotBlank(message = "手机号码不能为空!")
    12. @IsMobile
    13. private String mobile;
    14. @NotBlank(message = "密码不能为空!")
    15. private String password;
    16. }
    IsMobile:
    1. package com.xbb.spbootpro.validator;
    2. import javax.validation.Constraint;
    3. import javax.validation.Payload;
    4. import java.lang.annotation.*;
    5. @Documented
    6. @Constraint(
    7. validatedBy = {MobileValidator.class}
    8. )
    9. @Target({ElementType.METHOD, ElementType.FIELD, ElementType.ANNOTATION_TYPE, ElementType.CONSTRUCTOR, ElementType.PARAMETER, ElementType.TYPE_USE})
    10. @Retention(RetentionPolicy.RUNTIME)
    11. public @interface IsMobile {
    12. boolean required() default true;
    13. String message() default "手机号码格式错误!";
    14. Class[] groups() default {};
    15. Classextends Payload>[] payload() default {};
    16. }
    UserController:
    1. package com.xbb.spbootpro.controller;
    2. import com.xbb.spbootpro.model.dto.UserDto;
    3. import com.xbb.spbootpro.service.IUserService;
    4. import com.xbb.spbootpro.utils.JsonResponseBody;
    5. import org.springframework.beans.factory.annotation.Autowired;
    6. import org.springframework.web.bind.annotation.RequestMapping;
    7. import org.springframework.web.bind.annotation.RestController;
    8. import javax.servlet.http.HttpServletRequest;
    9. import javax.servlet.http.HttpServletResponse;
    10. import javax.validation.Valid;
    11. /**
    12. *

    13. * 用户信息表 前端控制器
    14. *

    15. *
    16. * @author xbb
    17. * @since 2022-11-09
    18. */
    19. @RestController
    20. @RequestMapping("/user")
    21. public class UserController {
    22. @Autowired
    23. private IUserService userService;
    24. @RequestMapping("/toLogin")
    25. public JsonResponseBody toLogin(@Valid UserDto userDto,
    26. HttpServletRequest req,
    27. HttpServletResponse resp){
    28. return userService.toLogin(userDto,req,resp);
    29. }
    30. }
    UserServiceImpl:
    1. package com.xbb.spbootpro.service.impl;
    2. import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
    3. import com.xbb.spbootpro.exception.BusinessException;
    4. import com.xbb.spbootpro.model.User;
    5. import com.xbb.spbootpro.mapper.UserMapper;
    6. import com.xbb.spbootpro.model.dto.UserDto;
    7. import com.xbb.spbootpro.service.IUserService;
    8. import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
    9. import com.xbb.spbootpro.utils.JsonResponseBody;
    10. import com.xbb.spbootpro.utils.JsonResponseStatus;
    11. import org.springframework.beans.factory.annotation.Autowired;
    12. import org.springframework.stereotype.Service;
    13. import javax.servlet.http.HttpServletRequest;
    14. import javax.servlet.http.HttpServletResponse;
    15. /**
    16. *

    17. * 用户信息表 服务实现类
    18. *

    19. *
    20. * @author xbb
    21. * @since 2022-11-09
    22. */
    23. @Service
    24. public class UserServiceImpl extends ServiceImpl implements IUserService {
    25. @Autowired
    26. private UserMapper userMapper;
    27. @Override
    28. public JsonResponseBody toLogin(UserDto userDto, HttpServletRequest req, HttpServletResponse resp) {
    29. // 1.5.1)判断mobile和password是否为空
    30. // 1.5.2)判断mobile格式是否正确
    31. // 1.5.3)根据用户手机号码查询用户是否存在
    32. User user= userMapper.selectOne(new QueryWrapper().eq("id",userDto.getMobile()));
    33. // 1.5.4)校验账号
    34. if(user==null){
    35. throw new BusinessException(JsonResponseStatus.USER_USERNAME_ERROR);
    36. }
    37. // 1.5.5)校验密码
    38. if(userDto.getPassword().equals(user.getPassword())){
    39. throw new BusinessException(JsonResponseStatus.USER_USERNAME_ERROR);
    40. }
    41. return new JsonResponseBody();
    42. }
    43. }

    效果:

    什么也不填:

    写了正确的手机号:

    密码正确,手机号错误

    3.3.盐加密

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

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

    后台加密:

    MD5Utils:
    1. package com.xbb.spbootpro.utils;
    2. import org.apache.commons.codec.digest.DigestUtils;
    3. import org.springframework.stereotype.Component;
    4. import java.util.UUID;
    5. /**
    6. * MD5加密
    7. * 用户端:password=MD5(明文+固定Salt)
    8. * 服务端:password=MD5(用户输入+随机Salt)
    9. * 用户端MD5加密是为了防止用户密码在网络中明文传输,服务端MD5加密是为了提高密码安全性,双重保险。
    10. */
    11. @Component
    12. public class MD5Utils {
    13. //加密盐,与前端一致
    14. private static String salt="f1g2h3j4";
    15. /**
    16. * md5加密
    17. * @param src
    18. * @return
    19. */
    20. public static String md5(String src){
    21. return DigestUtils.md5Hex(src);
    22. }
    23. /**
    24. * 获取加密的盐
    25. * @return
    26. */
    27. public static String createSalt(){
    28. return UUID.randomUUID().toString().replace("-","");
    29. }
    30. /**
    31. * 将前端的明文密码通过MD5加密方式加密成后端服务所需密码
    32. * 注意:该步骤实际是在前端完成!!!
    33. * @param inputPass 明文密码
    34. * @return
    35. */
    36. public static String inputPassToFormpass(String inputPass){
    37. //混淆固定盐salt,安全性更可靠
    38. String str=salt.charAt(1)+""+salt.charAt(5)+inputPass+salt.charAt(0)+""+salt.charAt(3);
    39. return md5(str);
    40. }
    41. /**
    42. * 将后端密文密码+随机salt生成数据库的密码
    43. * @param formPass
    44. * @param salt
    45. * @return
    46. */
    47. public static String formPassToDbPass(String formPass,String salt){
    48. //混淆固定盐salt,安全性更可靠
    49. String str=salt.charAt(7)+""+salt.charAt(4)+formPass+salt.charAt(1)+""+salt.charAt(5);
    50. return md5(str);
    51. }
    52. /**
    53. * 将用户输入的密码转换成数据库的密码
    54. * @param inputPass 明文密码
    55. * @param salt 盐
    56. * @return
    57. */
    58. public static String inputPassToDbPass(String inputPass,String salt){
    59. String formPass = inputPassToFormpass(inputPass);
    60. String dbPass = formPassToDbPass(formPass, salt);
    61. return dbPass;
    62. }
    63. public static void main(String[] args) {
    64. //d7aaa28e3b8e6c88352bd5e7c23829f9
    65. //5512a78a188b318c074a15f9b056a712
    66. String formPass = inputPassToFormpass("123456");
    67. System.out.println("前端加密密码:"+formPass);
    68. String salt = createSalt();
    69. System.out.println("后端加密随机盐:"+salt);
    70. String dbPass = formPassToDbPass(formPass, salt);
    71. System.out.println("后端加密密码:"+dbPass);
    72. System.out.println("-------------------------------------------");
    73. String dbPass1 = inputPassToDbPass("123456", salt);
    74. System.out.println("最终加密密码:"+dbPass1);
    75. }
    76. }

     前台加密:

    login.js:

    1. $(function () {
    2. alert(6);
    3. //登陆向后台发送ajax请求
    4. $("#login").click(function () {
    5. let mobile = $("#mobile").val();
    6. let password = $("#password").val();
    7. //1.密码加密
    8. //1) 定义固定盐
    9. let salt='f1g2h3j4';
    10. //2) 固定盐混淆
    11. let temp=salt.charAt(1)+""+salt.charAt(5)+password+salt.charAt(0)+""+salt.charAt(3);
    12. //3) 使用MD5完成前端第一次加密
    13. let pwd=md5(temp);
    14. $.post("/user/toLogin",{
    15. mobile:mobile,
    16. password:password
    17. },function (res) {
    18. alert(res.msg)
    19. },"json");
    20. });
    21. });
    UserServiceImpl:
    1. package com.xbb.spbootpro.service.impl;
    2. import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
    3. import com.xbb.spbootpro.exception.BusinessException;
    4. import com.xbb.spbootpro.model.User;
    5. import com.xbb.spbootpro.mapper.UserMapper;
    6. import com.xbb.spbootpro.model.dto.UserDto;
    7. import com.xbb.spbootpro.service.IUserService;
    8. import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
    9. import com.xbb.spbootpro.utils.JsonResponseBody;
    10. import com.xbb.spbootpro.utils.JsonResponseStatus;
    11. import com.xbb.spbootpro.utils.MD5Utils;
    12. import org.springframework.beans.factory.annotation.Autowired;
    13. import org.springframework.stereotype.Service;
    14. import javax.servlet.http.HttpServletRequest;
    15. import javax.servlet.http.HttpServletResponse;
    16. /**
    17. *

    18. * 用户信息表 服务实现类
    19. *

    20. *
    21. * @author xbb
    22. * @since 2022-11-09
    23. */
    24. @Service
    25. public class UserServiceImpl extends ServiceImpl implements IUserService {
    26. @Autowired
    27. private UserMapper userMapper;
    28. @Override
    29. public JsonResponseBody toLogin(UserDto userDto, HttpServletRequest req, HttpServletResponse resp) {
    30. // 1.5.1)判断mobile和password是否为空
    31. // 1.5.2)判断mobile格式是否正确
    32. // 1.5.3)根据用户手机号码查询用户是否存在
    33. User user= userMapper.selectOne(new QueryWrapper().eq("id",userDto.getMobile()));
    34. // 1.5.4)校验账号
    35. if(user==null){
    36. throw new BusinessException(JsonResponseStatus.USER_USERNAME_ERROR);
    37. }
    38. //前台传递到后台的密码,要进过工具类md5加密一次,才有可能跟数据库密码匹配上
    39. String pwd = MD5Utils.formPassToDbPass(userDto.getPassword(),user.getSalt());
    40. // 1.5.5)校验密码
    41. if(!pwd.equals(user.getPassword())){
    42. throw new BusinessException(JsonResponseStatus.USER_USERNAME_ERROR);
    43. }
    44. return new JsonResponseBody();
    45. }
    46. }

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

    UserServiceImpl.java变更如下

    1. package com.xbb.spbootpro.service.impl;
    2. import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
    3. import com.xbb.spbootpro.exception.BusinessException;
    4. import com.xbb.spbootpro.model.User;
    5. import com.xbb.spbootpro.mapper.UserMapper;
    6. import com.xbb.spbootpro.model.dto.UserDto;
    7. import com.xbb.spbootpro.service.IRedisService;
    8. import com.xbb.spbootpro.service.IUserService;
    9. import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
    10. import com.xbb.spbootpro.utils.CookieUtils;
    11. import com.xbb.spbootpro.utils.JsonResponseBody;
    12. import com.xbb.spbootpro.utils.JsonResponseStatus;
    13. import com.xbb.spbootpro.utils.MD5Utils;
    14. import org.springframework.beans.factory.annotation.Autowired;
    15. import org.springframework.stereotype.Service;
    16. import javax.servlet.http.HttpServletRequest;
    17. import javax.servlet.http.HttpServletResponse;
    18. import java.util.UUID;
    19. /**
    20. *

    21. * 用户信息表 服务实现类
    22. *

    23. *
    24. * @author xbb
    25. * @since 2022-11-09
    26. */
    27. @Service
    28. public class UserServiceImpl extends ServiceImpl implements IUserService {
    29. @Autowired
    30. private UserMapper userMapper;
    31. @Autowired
    32. private IRedisService iRedisService;
    33. @Override
    34. public JsonResponseBody toLogin(UserDto userDto, HttpServletRequest req, HttpServletResponse resp) {
    35. // 1.5.1)判断mobile和password是否为空
    36. // 1.5.2)判断mobile格式是否正确
    37. // 1.5.3)根据用户手机号码查询用户是否存在
    38. User user= userMapper.selectOne(new QueryWrapper().eq("id",userDto.getMobile()));
    39. // 1.5.4)校验账号
    40. if(user==null){
    41. throw new BusinessException(JsonResponseStatus.USER_USERNAME_ERROR);
    42. }
    43. //前台传递到后台的密码,要进过工具类md5加密一次,才有可能跟数据库密码匹配上
    44. String pwd = MD5Utils.formPassToDbPass(userDto.getPassword(),user.getSalt());
    45. // 1.5.5)校验密码
    46. if(!pwd.equals(user.getPassword())){
    47. throw new BusinessException(JsonResponseStatus.USER_USERNAME_ERROR);
    48. }
    49. //6.将登陆用户对象与token令牌进行绑定保存到cookie和redis
    50. //创建登陆令牌token
    51. String token= UUID.randomUUID().toString().replace("-","");
    52. //将token令牌保存到cookie中
    53. CookieUtils.setCookie(req,resp,"token",token,7200);
    54. //将登陆token令牌与用户对象user绑定到redis中
    55. iRedisService.setUserToRedis(token,user);
    56. //将用户登陆的昵称设置到cookie中
    57. CookieUtils.setCookie(req,resp,"nickname",user.getNickname());
    58. return new JsonResponseBody<>();
    59. }
    60. }
    IRedisService.java
    1. package com.xbb.spbootpro.service;
    2. import com.xbb.spbootpro.model.User;
    3. /**
    4. * @author冰冰
    5. * @create  2022-11-10 16:39
    6. */
    7. public interface IRedisService {
    8. void setUserToRedis(String token, User user);
    9. User getUserByToken(String token);
    10. }
    RedisServiceImpl:
    1. package com.xbb.spbootpro.service.impl;
    2. import com.xbb.spbootpro.model.User;
    3. import com.xbb.spbootpro.service.IRedisService;
    4. import org.springframework.beans.factory.annotation.Autowired;
    5. import org.springframework.data.redis.core.RedisTemplate;
    6. import org.springframework.stereotype.Service;
    7. /**
    8. * @author冰冰
    9. * @create  2022-11-10 16:43
    10. */
    11. @Service
    12. public class RedisServiceImpl implements IRedisService {
    13. @Autowired
    14. private RedisTemplate redisTemplate;
    15. @Override
    16. public void setUserToRedis(String token, User user) {
    17. redisTemplate.opsForValue().set("user:"+token,user,7200L);
    18. }
    19. @Override
    20. public User getUserByToken(String token) {
    21. return (User) redisTemplate.opsForValue().get("user:"+token);
    22. }
    23. }

  • 相关阅读:
    ERROR: your rosdep installation has not been initialized yet
    软航H5 PDF签章产品经nginx代理之后浏览器中PDF盖章时提示:签章失败:网络错误 的问题排查及解决办法
    车载高速CAN(HighSpeed CAN)通信之CAN Bus Off
    MCS:多元随机变量——离散随机变量
    Xilinx IP 10G Ethernet PCS/PMA IP Core
    国产信创的“芯“动力之海光CPU剖析
    mimkatz获取windows10明文密码
    if条件分支计算分段函数
    逆向进阶,利用 AST 技术还原 JavaScript 混淆代码
    你要了解,哪些财产不属于夫妻共同财产
  • 原文地址:https://blog.csdn.net/m0_68211831/article/details/127750313