Java项目 苍穹外卖 黑马程序员

news2024/11/26 1:38:12

目录

  • day1
    • 一、项目效果展示
    • 二、项目开发整体介绍
    • 三、项目介绍
      • 3.1 定位
      • 3.2 功能架构
      • 3.3 产品原型
      • 3.4 技术选型
    • 四、开发环境搭建
      • 4.1 前端环境
      • 4.2 后端环境
    • 五、导入接口文档
    • 六、Swagger
      • 6.1 介绍
      • 6.2 使用方式
      • 6.3 常用注解
  • day2
    • 一、新增员工
    • 二、员工分页查询
    • 三、启用禁用员工账号
    • 四、编辑员工
    • 五、导入分类模块功能代码
  • day3

来源: 黑马程序员Java项目实战《苍穹外卖》,最适合新手的SpringBoot+SSM的企业级Java项目实战

day1

一、项目效果展示

二、项目开发整体介绍

在这里插入图片描述

三、项目介绍

3.1 定位

在这里插入图片描述

3.2 功能架构

在这里插入图片描述

3.3 产品原型

html页面,包括管理端和用户端两种

3.4 技术选型

在这里插入图片描述

四、开发环境搭建

在这里插入图片描述

4.1 前端环境

前端工程是基于nginx运行的,已经是打包好的程序,直接双击执行exe文件,接着在浏览器访问localhost即可。
在这里插入图片描述
在这里插入图片描述

4.2 后端环境

后端工程是基于maven进行构建的,并且进行分模块开发
导入的时候,需要配置maven的settings文件中阿里云镜像
在这里插入图片描述
在这里插入图片描述

  1. 使用git进行版本控制:本地创建仓库,远程创建仓库,将本地仓库推送到远程
  2. 数据库环境搭建:导入数据库文件即可
  3. 前后端联调:通过断点调试,一步步理清登录功能。
1.获取前端对象(employeeLoginDTO)
2.使用DTO中username属性通过EmployeeMapper查询数据库,得到emplyee对象
3.判断密码是否一致,且用户状态是否为‘启用’,都是则登录成功
4.生成JWK令牌,通过配置文件获取密钥和过期时间,令牌名称为token
5.通过Builder注解的方法生成employeeLoginVO对象,包括主键值、用户名、姓名和jwt令牌
6.后端统一返回结果为Result<T>,封装了错误信息msg和返回的VO对象
7.另外,文件中定义了各种异常,继承自BaseException,它的父类为RuntimeException。通过全局处理器handler来捕获全部的异常,进行处理

在这里插入图片描述

  1. 前端发送的请求,如何请求到后端服务的?
    是通过nginx方向代理,将前端发送的动态请求有nginx转发到后端服务器
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

  2. 完善登录功能
    在数据库中加密存储密码—> 在server登录功能处,将明文密码先加密在进行对比

五、导入接口文档

接口设计能力
前后端分离开发流程。使用apifox导入接口json文件。划分了两个文件,包括管理端和用户端。
在这里插入图片描述

六、Swagger

6.1 介绍

在这里插入图片描述

6.2 使用方式

在这里插入图片描述
在这里插入图片描述
最后去网页访问http://localhost:8080/doc.html,会出现下面的界面
在这里插入图片描述
在这里插入图片描述

6.3 常用注解

在这里插入图片描述

day2

一、新增员工

  1. 根据接口文档,写service。EmployeeController.java
	/**
     * 新增员工
     * @param employeeDTO
     * @return
     */
    @PostMapping
    @ApiOperation("新增员工")
    public Result save(@RequestBody EmployeeDTO employeeDTO){
        log.info("新增员工:{}", employeeDTO);
        employeeService.save(employeeDTO);
        return  Result.success();
    }
  1. 完善EmployeeService接口和EmployeeServiceImpl接口实现类的save方法。EmployeeServiceImpl.java
    /**
     * 新增员工
     * @param employeeDTO
     */
    public void save(EmployeeDTO employeeDTO) {
        // 对象的转换,将DTO转为实体对象
        Employee employee = new Employee();
        // 对象属性拷贝,将dto对象拷贝给entity。DTO和entity对象的属性名有一部分一致
        BeanUtils.copyProperties(employeeDTO,employee);

        // 对entity的其他属性初始化
        employee.setStatus(StatusConstant.ENABLE); //状态
        employee.setPassword(DigestUtils.md5DigestAsHex(PasswordConstant.DEFAULT_PASSWORD.getBytes())); //密码
        employee.setCreateTime(LocalDateTime.now()); //创建时间
        employee.setUpdateTime(LocalDateTime.now()); //修改时间
        // todo 后期需要改为当前用户的属性
        employee.setCreateUser(10L); //创建人
        employee.setUpdateUser(10L); //修改人

        employeeMapper.insert(employee);
    }
  1. 完善EmployeeMapper接口中的sql。EmployeeMapper.java
    /**
     * 插入员工数据
     * @param employee
     */
    @Insert("insert into employee (name, username, password, phone, sex, id_number, status, create_time, update_time, " +
            "create_user, update_user) values (#{name}, #{username}, #{password}, #{phone}, #{sex}, #{idNumber}, " +
            "#{status}, #{createTime}, #{updateTime}, #{createUser}, #{updateUser})")
    void insert(Employee employee);
  1. 通过接口文档测试功能(常用)或者是前后端联调测试。
    通过接口文档测试的时候,发出的请求需要带上token令牌。因此需要添加一个全局变量,名称为token。
    在这里插入图片描述
  2. 完善登录功能。重复录入,抛出异常没有处理;新增员工,创建人和修改人设置的是固定值。完善好仍要进行测试。
    在这里插入图片描述
    在这里插入图片描述
//1.重复录入,异常处理即可
//GlobalExceptionHandler.java
    /**
     * 处理sql异常
     * @param ex
     * @return
     */
    @ExceptionHandler
    public Result exceptionHandler(SQLIntegrityConstraintViolationException ex){
        String message = ex.getMessage();
        if(message.contains("Duplicate entry")){
            String username = message.split(" ")[2];
            String msg = username + MessageConstant.ALREADY_EXISTS;
            return Result.error(msg);
        }else{
            return Result.error(MessageConstant.UNKNOWN_ERROR);
        }
    }


//2.使用threadLocal方法解决获取当前用户id
//BaseContext.java
package com.sky.context;

public class BaseContext {

    public static ThreadLocal<Long> threadLocal = new ThreadLocal<>();

    public static void setCurrentId(Long id) {
        threadLocal.set(id);
    }

    public static Long getCurrentId() {
        return threadLocal.get();
    }

    public static void removeCurrentId() {
        threadLocal.remove();
    }

}
//JwtTokenAdminInterceptor.java
BaseContext.setCurrentId(empId);
//EmployeeServiceImpl.java
employee.setCreateUser(BaseContext.getCurrentId()); //创建人
employee.setUpdateUser(BaseContext.getCurrentId()); //修改人

二、员工分页查询

//EmployeeController.java
	/**
     * 员工分页查询
     * @param employeePageQueryDTO
     * @return
     */
    @GetMapping
    @ApiOperation("员工分页查询")
    public Result<PageResult> pageQuery(EmployeePageQueryDTO employeePageQueryDTO){
        log.info("员工分页查询,参数为:{}", employeePageQueryDTO);
        PageResult pageResult = employeeService.pageQuery(employeePageQueryDTO);
        return Result.success(pageResult);
    }

//EmployeeServiceImpl.java
    /**
     * 员工分页查询
     * @param employeePageQueryDTO
     * @return
     */
    @Override
    public PageResult pageQuery(EmployeePageQueryDTO employeePageQueryDTO) {
        //select * from employee limit 0,10
        //开始分页查询
        PageHelper.startPage(employeePageQueryDTO.getPage(),employeePageQueryDTO.getPageSize());
        Page<Employee> page = employeeMapper.pageQuery(employeePageQueryDTO);
        long total = page.getTotal();
        List<Employee> records = page.getResult();
        return new PageResult(total, records);
    }
  
//EmployeeMapper.java
    /**
     * 员工分页查询
     * @param employeePageQueryDTO
     * @return
     */
    Page<Employee> pageQuery(EmployeePageQueryDTO employeePageQueryDTO);

//EmployeeMapper.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.sky.mapper.EmployeeMapper">
    <select id="pageQuery" resultType="com.sky.entity.Employee">
        select * from
        <where>
            <if test="name != null and name != ''">
                and name like concat('%',#{name},'%')
            </if>
        </where>
        order by create_time desc
    </select>
</mapper>

完善代码:1时间的问题
在这里插入图片描述

    /**
     * 扩张Spring MVC框架的消息转换器
     * @param converters
     */
    protected void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
        log.info("扩展消息转化器...");
        //创建一个消息转换器对象
        MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
        //需要为消息转换器设置一个对象转换器,对象转换器可以将Java对象序列化为json数据
        converter.setObjectMapper(new JacksonObjectMapper());
        //将自己的消息转换器加入容器中
        converters.add(0,converter);
    }

三、启用禁用员工账号

//EmployeeController.java
    /**
     * 启用禁用员工账号
     * @param status
     * @param id
     * @return
     */
    @PostMapping("/status/{status}")
    @ApiOperation("启用禁用员工账号")
    public Result startOrStop(@PathVariable Integer status, Long id){
        log.info("启用禁用员工账号:{},{}", status, id);
        employeeService.startOrStop(status,id);
        return Result.success();
    }

//EmployeeServiceImpl.java
    /**
     * 启用禁用员工账号
     * @param status
     * @param id
     * @return
     */
    public void startOrStop(Integer status, Long id) {
        //update employee set status=? where id = ?
        //为了更通用的使用update方法,在mapper中定义的是通用的update方法,每次传递一个实体对象,而不是修改的属性

//        Employee employee = new Employee();
//        employee.setStatus(status);
//        employee.setId(id);

        Employee employee = Employee.builder()
                .status(status)
                .id(id)
                .build();
        employeeMapper.update(employee);
    }

//EmployeeMapper.xml
    <update id="update" parameterType="com.sky.entity.Employee">
        update employee
        <set>
            <if test="name != null">name = #{name},</if>
            <if test="username != null">username = #{username},</if>
            <if test="password != null">password = #{password},</if>
            <if test="phone != null">phone = #{phone},</if>
            <if test="sex != null">sex = #{sex},</if>
            <if test="idNumber != null">id_number = #{idNumber},</if>
            <if test="status != null">status = #{status},</if>
            <if test="updateTime != null">update_time = #{updateTime},</if>
            <if test="updateUser != null">update_user = #{updateUser},</if>
        </set>
        where id = #{id}
    </update>

四、编辑员工

两个接口,根据id查询员工,修改员工信息

//EmployeeController.java
    /**
     * 根据id查询员工
     * @param id
     * @return
     */
    @GetMapping("/{id}")
    @ApiOperation("根据id查询员工")
    public Result<Employee> getById(@PathVariable Long id){
        Employee employee = employeeService.getById(id);
        return Result.success(employee);
    }

    /**
     * 编辑员工信息
     * @param employeeDTO
     * @return
     */
    @PutMapping
    @ApiOperation("编辑员工信息")
    public Result update(@RequestBody EmployeeDTO employeeDTO){
        log.info("编辑员工信息:{}", employeeDTO);
        employeeService.update(employeeDTO);
        return Result.success();
    }

//EmployeeServiceImpl.java
    /**
     * 根据id查询员工
     * @param id
     * @return
     */
    public Employee getById(Long id) {
        Employee employee = employeeMapper.getById(id);
        employee.setPassword("****"); // 将传给前端的密码设置为*
        return employee;
    }

    /**
     * 编辑员工信息
     * @param employeeDTO
     */
    public void update(EmployeeDTO employeeDTO) {
        Employee employee = new Employee();
        BeanUtils.copyProperties(employeeDTO,employee);
        employee.setUpdateTime(LocalDateTime.now());
        employee.setUpdateUser(BaseContext.getCurrentId());
        employeeMapper.update(employee);
    }

//EmployeeMapper.java
    /**
     * 根据id查询员工
     * @param id
     * @return
     */
    @Select("select  * from employee where id = #{id}")
    Employee getById(Long id);

五、导入分类模块功能代码

在这里插入图片描述

day3

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

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

相关文章

深度解析:基于隐马尔科夫模型的语音转文字技术

引言 语音转文字(Speech-to-Text, STT)技术作为人机交互的重要一环,在智能助手、自动字幕生成、语音命令识别等领域发挥着越来越重要的作用。隐马尔科夫模型(Hidden Markov Model, HMM)作为一种统计模型,因其在处理时间序列数据方面的优势,被广泛应用于语音识别系统中。…

蓝牙耳机推荐高性价比2024,运用六大实战技巧,精准捕获超值机型

​无论是通勤路上、健身房里&#xff0c;还是在家中放松时&#xff0c;蓝牙耳机都是我们享受音乐、提升生活品质的好帮手。随着蓝牙耳机技术的快速发展&#xff0c;各种款式层出不穷&#xff0c;选择起来确实不易。作为一名耳机发烧友&#xff0c;我认为是时候向大家推荐几款质…

Springboot+Vue项目-基于Java+MySQL的房屋租赁系统(附源码+演示视频+LW)

大家好&#xff01;我是程序猿老A&#xff0c;感谢您阅读本文&#xff0c;欢迎一键三连哦。 &#x1f49e;当前专栏&#xff1a;Java毕业设计 精彩专栏推荐&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb; &#x1f380; Python毕业设计 &…

Hive 解决数据倾斜方法

数据倾斜问题&#xff0c; 通常是指参与计算的数据分布不均&#xff0c; 即某个 key 或者某些 key 的数据量远超其他 key&#xff0c; 导致在 shuffle 阶段&#xff0c; 大量相同 key 的数据被发往同一个 Reduce&#xff0c; 进而导致该 Reduce 所需的时间远超其他 Reduce&…

深入探索生产者拦截器的使用以及源码设计

文章目录 一、介绍二、使用1. ProducerInterceptor接口2. 实现之统计3. 实现之二次处理4. 小结 三、实现原理1. 初始化流程2. 生效流程 四、总结 一、介绍 在软件设计中&#xff0c;为了方便能够应对不同的场景&#xff0c;一般在一些容易有差异的环节会考虑允许用户自定义逻辑…

数据结构(图)

定义 G (V, E) 图 (点&#xff0c;边) 图&#xff0c;Graph 点&#xff0c;Vertex 边&#xff0c;edge 有空表&#xff0c;空树&#xff0c;但没有空图 图可以没有边|E| 0&#xff0c;但不能没有一个点 稠密图 &稀疏图 是边的多少决定的 &#xff08;见Ex…

今日早报 每日精选15条新闻简报 每天一分钟 知晓天下事 4月19日,星期五

每天一分钟&#xff0c;知晓天下事&#xff01; 2024年4月19日 星期五 农历三月十一 谷雨 1、 景海鹏获颁特级航天功勋奖章&#xff0c;朱杨柱、桂海潮被授予英雄航天员称号。 2、 工信部&#xff1a;加快6G、万兆光网研发力度&#xff0c;加速推进大数据、AI等研发应用。 3、…

NAND数据恢复的方案

NAND Flash是固态硬盘&#xff08;SSD&#xff09;的核心数据存储。然而&#xff0c;NAND Flash因其物理特性和工作原理&#xff0c;存在一定的内在脆弱性&#xff0c;尤其是在数据存储的长期可靠性方面。 比特错误是指在读取NAND Flash时&#xff0c;原本存储的二进制位&#…

单输入多输出(SIMO)和多输入多输出(MIMO)模型是什么?

当谈到单输入多输出&#xff08;SIMO&#xff09;和多输入多输出&#xff08;MIMO&#xff09;模型时&#xff0c;通常指的是工程和信号处理领域中的系统和算法。我列举了一些我研究过的实例&#xff1a; 单输入多输出&#xff08;SIMO&#xff09;&#xff1a; 多标签分类器&a…

RK3588 开发板的魅力所在!

处理器是计算机硬件系统的核心部件&#xff0c;其性能的提升对于设备功能和用户体验起着重要的作用。处理器也是开发板的核心&#xff0c;它决定了其计算性能和图形性能。那么&#xff0c;RK3588处理器属于什么档次&#xff1f;其性能和市场定位如何&#xff1f;市场上有哪些用…

C++信奥教学PPT:CSP_J_算法之双指针算法(中)

1、⼀个⻓度为 n-1 的递增排序数组中的所有数字都是唯⼀的&#xff0c;并且每个数字都在范围0&#xff5e;n-1 之内。在范围 0&#xff5e; n-1 内的 n 个数字中有且只有⼀个数字不在该数组中&#xff0c;请找出这个数字。 2、循环最大值&#xff08;Maximum in the Cycle of 1…

TSINGSEE青犀算法中台消防通道堵塞/占压AI检测算法的介绍及应用

消防通道是建筑物内用于紧急疏散的通道&#xff0c;其畅通无阻对于保障人员生命安全至关重要。然而&#xff0c;由于各种原因&#xff0c;消防通道经常会被杂物、车辆等堵塞&#xff0c;一旦发生火灾等紧急情况&#xff0c;后果不堪设想。为了有效解决这一问题&#xff0c;我们…

去除【关注博主即可阅读全文】插件

这两天闲着没事看csdn&#xff0c;看到好多博主弄这个关注才可以看文章 正好好久没写过那个油猴的插件&#xff0c;今天就用油猴写个这玩意。大家可以试着玩 代码我贴下面了&#xff0c;想用自取啊 // UserScript // name 去除关注才可以阅读 // namespace http:/…

项目实战:Qt获取CTP量化交易接口测试数据工具 v1.0.0(获取深度行情数据、订阅取消订阅)

若该文为原创文章&#xff0c;转载请注明出处 本文章博客地址&#xff1a;https://hpzwl.blog.csdn.net/article/details/137937666 红胖子(红模仿)的博文大全&#xff1a;开发技术集合&#xff08;包含Qt实用技术、树莓派、三维、OpenCV、OpenGL、ffmpeg、OSG、单片机、软硬结…

Python教学入门:函数

在 Python 中&#xff0c;def 关键字用于定义函数。函数是一段可重用的代码块&#xff0c;用于执行特定的任务或操作。通过定义函数&#xff0c;可以将一段代码封装起来&#xff0c;使其可以在程序中被多次调用&#xff0c;提高代码的复用性和可维护性。 下面是 def 函数定义的…

安装docker的PHP环境NLMP环境在国产deepin操作系统上

1: 先安装docker 安装完后执行,权限设置 sudo usermod -aG docker $USER或者sudo usermod -aG docker kentrl#添加当前用户到Docker用户组中 sudo newgrp docker#更新用户组数据,必须执行否则无效 sudo systemctl restart docker 先看目录结构: 2:按照目录结构挂载磁盘,…

MLP/CNN/RNN/Transformer主流深度学习模型的区别

1. 多层感知机(MLP) 核心特征: 结构:MLP 是一种基本的前馈神经网络,包含一个输入层、一个或多个隐藏层以及一个输出层。每层由全连接的神经元组成。用途:适用于简单的分类和回归任务。限制:不适用于处理序列数据或图像数据,因为它不具备处理输入之间时间或空间关系的能…

IDEA @Autowired不显示红线

IDEA 中&#xff0c;Autowired 显示红线一般情况是注入 Mapper 或者 Dao 时出现的&#xff0c;如下图&#xff1a; 这个报错是因为 Mapper 或者 Dao 上没有加 Repository 或者 Mapper&#xff0c;Autowired 注入时就判断为这不是一个 Bean。 不建议通过加上面两个注解的方式解…

python自动化之网易自动点歌

这个代码是是使用的pyautogui库和pyperclip库完成的&#xff0c;这个库是开源的地址如下&#xff1a;https://github.com/asweigart/pyautogui这里详细的用法想学习的可以到这看看 下面是代码&#xff1a; import pyautogui import subprocess import pyperclip import time i…

ubuntu设置扩充swap交换空间

Swap是指Linux系统中的交换分区,类似于Windows的虚拟内存,当内存不足的时候,把一部分硬盘空间虚拟成内存来使用,从而解决内存不足的问题。交换分区,它的功能就是在内存不够的情况下,操作系统先把内存中暂时不用的数据,存到硬盘的交换空间,腾出内存来让别的程序运行! …