项目--苍穹外卖

1.| constant | 存放相关常量类 |
| context | 存放上下文类 |
| enumeration | 项目的枚举类存储 |
| exception | 存放自定义异常类 |
| json | 处理json转换的类 |
| properties | 存放SpringBoot相关的配置属性类 |
| result | 返回结果类的封装 |
| utils | 常用工具类 |
2.| Entity | 实体,通常和数据库中的表对应 |
| DTO | 数据传输对象,通常用于程序中各层之间传递数据 |
| VO | 视图对象,为前端展示数据提供的对象 |

| POJO | 普通Java对象,只有属性和对应的getter和setter |

3.| config | 存放配置类 |
| controller | 存放controller类 |
| interceptor | 存放拦截器类 |
| mapper | 存放mapper接口 |
| service | 存放service类 |
| SkyApplication | 启动类 |

3.先编译一下,然后正常运行

 前后端联调:

nginx反向代理,就是将前端发送的动态请求由nginx转发到后端服务器

好处: 

前端发送的请求,是如何请求到后端服务的?

在使用Nginx作为反向代理的Java项目中,前端发送的请求会被Nginx接收并处理,然后转发给后端服务。以下是一些基本步骤:

客户端(前端)发送请求到Nginx服务器。
Nginx服务器接收请求,并根据配置的规则进行处理。
Nginx根据配置的规则将请求转发给后端服务。
后端服务接收到请求并处理,然后返回响应。
Nginx接收后端服务的响应,并将其返回给客户端。

在这个过程中,Nginx扮演了反向代理的角色,接收客户端的请求并转发给后端服务,同时也将后端服务的响应返回给客户端。通过Nginx,可以实现对请求的负载均衡(把大量的请求按照我们指定的方式均衡的分配给集中的每台服务器)、缓存、安全过滤等处理,提高系统的性能和安全性。 

配置:nginx.conf

server{     

             listen 80;     

             server_name localhost;          

             location /api/ {                     

                             proxy_pass   http://localhost:8080/admin/;  #反向代理     } }

nginx 负载均衡的配置方式: nginx.conf

upstream webservers{     

                server 192.168.100.128:8080;     

                server 192.168.100.129:8080;

}

server{     listen 80;     

                server_name localhost;          

                location /api/ {                   

                                proxy_pass   http://webservers/admin/;  #负载均衡     } }

完善登录功能

问题:员工表中的密码是明文存储,安全性太低。 

1.将密码加密后存储,提高安全性

2.使用MD5加密方式对明文密码加密

1.修改数据库中明文密码,改为MD5加密后的密文

2.修改Java代码,前端提交的密码进行MD5加密后再跟数据库中密码比对

在EmployeeServiceImpl中

//进行md5加密,然后再进行比对

password = DigestUtils.md5DigestAsHex(password.getBytes());

if (!password.equals(employee.getPassword())) {    

//密码错误  

throw new PasswordErrorException(MessageConstant.PASSWORD_ERROR); }

前后端 分离开发流程:

导入接口文档 

json导入YApi

Yapi 是设计阶段使用的工具,管理和维护接口

Swagger 在开发阶段使用的框架,帮助后端开发人员做后端的接口测试

Swagger

使用Swagger你只需要按照它的规范去定义接口及接口相关的信息,就可以做到生成接口文档,以及在线接口调试页面。

Knife4j 是为Java MVC框架集成Swagger生成Api文档的增强解决方案。

1.导入maven坐标

2.在配置类中加入knnife4j相关配置

3.设置静态资源映射,否则接口文档页面无法访问

<dependency>            

<groupId>com.github.xiaoymin</groupId>            

<artifactId>knife4j-spring-boot-starter</artifactId>            

<version>3.0.2</version>

</dependency>

 WebMvcConfiguration中:

@Bean

public Docket docket(){    

    ApiInfo apiInfo = new ApiInfoBuilder()            

                .title(“苍穹外卖项目接口文档”)            

                .version(“2.0”)            

                .description(“苍穹外卖项目接口文档")            

                .build();    

Docket docket = new Docket(DocumentationType.SWAGGER_2)            

           .apiInfo(apiInfo)            

           .select()            

           //指定生成接口需要扫描的包      .apis(RequestHandlerSelectors.basePackage("com.sky.controller"))                          .paths(PathSelectors.any())            

        .build();

return  docket;

}

/* * 
*设置静态资源映射 ,主要是访问接口文档
* @param registry
*/
protected void addResourceHandlers(ResourceHandlerRegistry registry) {
   log.info(“开始设置静态资源映射...");   
   registry.addResourceHandler("/doc.html").addResourceLocations("classpath:/META-INF/resources/");    
   registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/");
   }

常用注解:

通过注解可以控制生成的接口文档,使接口文档拥有更好的可读性,常用注解如下:

@Api(tags ="员工相关接口")

@ApiOperation(value = "员工登录")    方法上

@ApiOperation("员工退出")

DTO:专注于做数据传输

当前端提交的数据和实体类中对应的属性差别比较大时,建议使用DTO来封装数据

VO

新增员工

@PostMapping
@ApiOperation("新增员工")
public Result save(@RequestBody EmployeeDTO employeeDTO){
log.info("新增员工:{}",employeeDTO);
employeeService.save(employeeDTO);
return Result.success();
}

void save(EmployeeDTO employeeDTO); 

@Override
public void save(EmployeeDTO employeeDTO) {
Employee employee = new Employee();
//employee.setName(employeeDTO.getName());

//对象属性拷贝
BeanUtils.copyProperties(employeeDTO,employee);
//设置账号的状态,默认正常状态1表示正常,0表示锁定
employee.setStatus(StatusConstant.ENABLE);

//设置密码,默认123456
employee.setPassword(DigestUtils.md5DigestAsHex(PasswordConstant.

DEFAULT_PASSWORD.getBytes()));

//设置当前记录的创建时间和修改时间
employee.setCreateTime(LocalDateTime.now());
employee.setUpdateTime(LocalDateTime.now());

//设置当前记录创建人id和修改人id
//TODO 后期需要改为当前登录用户的id
employee.setCreateUser(10L);
employee.setUpdateUser(10L);

employeeMapper.insert(employee);
}

  

@Insert("insert into employee (name,username,password,phone,sex,id_number,create_time,update_time," +
"create_user,update_user)" +"values "+
"(#{name},#{username},#{password},#{phone},#{sex},#{idNumber},#{createTime},#{updateTime},#{createUser},#{updateUser})")
void insert(Employee employee);

 

存在问题

1.录入的用户名已存在,抛出异常后没有处理

2.新增员工时,创建人id和修改人id设置为了固定值 

@ExceptionHandler
public Result exceptionHandler(SQLIntegrityConstraintViolationException ex) {
log.error("异常信息:{}", ex.getMessage());
Duplicate entry 'zhangsan' for key 'employee.idx username
String message = ex.getMessage(); //获得异常信息
if (message.contains("Duplicate entry")) { //判断异常信息里面有没有关键字Duplicate entry
String[] split = message.split(" "); //动态把字符串提取出来,根据空格分割,得到数组对象
String username = split[2]; //第三个,下标为2
String msg = username + MessageConstant.ALREADY_EXISTS; //用户名已存在
return Result.error(msg);
} else {
return Result.error(MessageConstant.UNKNOWN_ERROR);
}
}

 

解析出登录员工id后,如何传递给Service的save方法?

ThreadLocal 并不是一个Thread,而是Thread的局部变量。

ThreadLocal为每个线程提供单独一份存储空间,具有线程隔离的效果,只有在线程内才能获取到对应的值,线程外则不能访问。

ThreadLocal常用方法:

public void set(T value)     设置当前线程的线程局部变量的值

public T get()         返回当前线程所对应的线程局部变量的值

public void remove()        移除当前线程的线程局部变量 

注意:客户端发送的每次请求,后端的Tomcat服务器都会分配一个单独的线程来处理请求

员工分页查询

业务规则:

根据页码展示员工信息

每页展示10条数据

分页查询时可以根据需要,输入员工姓名进行查询

返回数据data:

total:总记录数   records:代表当前这一页要展示的数据集合,数据多个,为数组

根据分页查询接口设计对应的DTO:

@Data

public class EmployeePageQueryDTO implements Serializable {    

//员工姓名    

private String name;    

//页码    

private int page;    

//每页显示记录数     private int pageSize;

}

后面所有的分页查询,统一都封装成PageResult对象:

/**  * 封装分页查询结果  */

@Data

@AllArgsConstructor

@NoArgsConstructor

public class PageResult implements Serializable {    

private long total; //总记录数    

private List records; //当前页数据集合 }

员工信息分页查询后端返回的对象类型为:Result<PageResult>

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

PageResult pageQuery(EmployeePageQueryDTO employeePageQueryDTO); 

@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(); //records
return new PageResult(total,records);
}

Page<Employee> pageQuery(EmployeePageQueryDTO employeePageQueryDTO); 

  

<?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 employee
<where>
<if test="name !=null and name !=''">
and name like concat('%',#{name},'%')
</if>
</where>
order by create_time desc
</select>
</mapper>

日期格式 错误:

解决方式: 方式一:在属性上加入注解,对日期进行格式化

方式二:在 WebMvcConfiguration 中扩展Spring MVC的消息转换器,统一对日期类型进行格式化处理

配置类上

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

启用禁用员工账号

业务规则: 可以对状态为“启用” 的员工账号进行“禁用”操作 可以对状态为“禁用”的员工账号进行“启用”操作 状态为“禁用”的员工账号不能登录系统

根据接口设计中的请求参数形式对应的在 EmployeeController 中创建启用禁用员工账号的方法:

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

在 EmployeeService 接口中声明启用禁用员工账号的业务方法:

void startOrStop(Integer status, Long id);

 在 EmployeeServiceImpl 中实现启用禁用员工账号的业务方法:

@Override
public void startOrStop(Integer status, Long id) {
// Employee employee = new Employee();
// employee.setStatus(status);
// employee.setId(id);
Employee employee = Employee.builder()
.status(status)
.id(id)
.build();
//Update employee set status =?where id = ?
employeeMapper.update(employee);

}

在 EmployeeMapper 接口中声明 update 方法:

void updae(Employee employee);

在 EmployeeMapper.xml 中编写SQL:

<update id="update" parameterType="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="updateTime != null">update_Time = #{updateTime},</if>
<if test="updateUser != null">update_User = #{updateUser},</if>
<if test="status != null">status = #{status},</if>
</set>
where id = #{id}
</update>

编辑员工 

编辑员工功能涉及到两个接口: 根据id查询员工信息 编辑员工信息

在 EmployeeController 中创建 getById 方法:

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

在 EmployeeService 接口中声明 getById 方法: 

Employee getById(Long id); 

在 EmployeeServiceImpl 中实现 getById 方法: 

@Override
public Employee getById(Long id) {
Employee employee=employeeMapper.getById(id);
employee.setPassword("****");
return employee;
}

在 EmployeeMapper 接口中声明 getById 方法: 

@Select("select *from employee where id = #{id}")
Employee getById(Long id);

 在 EmployeeController 中创建 update 方法:

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

在 EmployeeService 接口中声明 update 方法: 

void update(EmployeeDTO employeeDTO);

 在 EmployeeServiceImpl 中实现 update 方法:

public void update(EmployeeDTO employeeDTO) {//通过DTO来接收前端提交过来的数据
//对象属性拷贝,给employee赋值
Employee employee = new Employee();
BeanUtils.copyProperties(employeeDTO, employee);
employee.setUpdateTime(LocalDateTime.now());
employee.setUpdateUser(BaseContext.getCurrentId());
employeeMapper.update(employee); //调用service方法
}

导入分类模块功能代码

业务规则:

分类名称必须是唯一

分类按照类型可以分为菜品分类和套餐分类

新添加的分类状态默认为“禁用” 

接口设计: 新增分类 分类分页查询 根据id删除分类 修改分类 启用禁用分类 根据类型查询分类

 

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Linux工具(一)

前言&#xff1a;Linux是一个开源的操作系统&#xff0c;它拥有庞大而活跃的开发社区&#xff0c;为用户提供了丰富多样的工具和应用程序。这些工具不仅适用于系统管理员和开发人员&#xff0c;也适用于普通用户&#xff0c;可以帮助他们完成各种任务&#xff0c;从简单的文件管…

宝塔面板日志和缓存占用磁盘空间很大,如何清理?

服务器使用的宝塔面板&#xff0c;最近发现服务器的“系统盘”快爆满了&#xff0c;点面板上日志管理都要收费&#xff0c;我也不是很懂服务器的运维&#xff0c;使用ai进行询问&#xff0c;得到了解决&#xff1a; /var/log 日志目录 运行下面的命令查找是哪些目录占用空间很…

嵌入式Linux驱动开发(I2C专题)(七)

使用GPIO操作I2C设备_IMX6ULL 参考资料&#xff1a; Linux文档 Linux-5.4\Documentation\devicetree\bindings\i2c\i2c-gpio.yamlLinux-4.9.88\Documentation\devicetree\bindings\i2c\i2c-gpio.txt Linux驱动源码 Linux-5.4\drivers\i2c\busses\i2c-gpio.cLinux-4.9.88\driv…

【SpringMVC】文件上传与下载、JREBEL使用

目录 一、引言 二、文件的上传 1、单文件上传 1.1、数据表准备 1.2、添加依赖 1.3、配置文件 1.4、编写表单 1.5、编写controller层 2、多文件上传 2.1、编写form表单 2.2、编写controller层 2.3、测试 三、文件下载 四、JREBEL使用 1、下载注册 2、离线设置 一…

Java增强for循环(学习笔记)

Java增强for循环 主要用于数组或者集合的增强型for循环。 格式&#xff1a; for(声明语句&#xff1a;表达式){ 代码句子 } 声明语句&#xff1a;声明新的局部变量&#xff0c;该变量的类型必须和数组元素的类型匹配。其作用域限定在循环语句块&#xff0c;其值与此时数组元…

Python 变量作用域

视频版教程 Python3零基础7天入门实战视频教程 在程序中定义一个变量时&#xff0c;这个变量是有作用范围的&#xff0c;变量的作用范围被称为它的作用域。根据定义变量的位置&#xff0c;变量分为两种。 局部变量。在函数中定义的变量&#xff0c;包括参数&#xff0c;都被称…

王道考研操作系统

王道考研操作系统 计算机系统概述操作系统的概念操作系统的特征操作系统的发展历程操作系统内核中断和异常![在这里插入图片描述](https://img-blog.csdnimg.cn/162452b4c60144e0bd500e180127c447.png)系统调用操作系统结构虚拟机错题 进程与线程进程控制进程通信线程和多线程模…

jvm中对象创建、内存布局以及访问定位

对象创建 Java语言层面&#xff0c;创建对象通常&#xff08;例外&#xff1a;复制、反序列化&#xff09;仅仅是一个new关键字即可&#xff0c;而在虚拟机中&#xff0c;对象&#xff08;限于普通Java对象&#xff0c;不包括数组和Class对象等&#xff09;的创建又是怎样一个过…

【直播预约中】 腾讯大数据 x StarRocks|构建新一代实时湖仓

随着信息时代的兴起&#xff0c;数据已成为推动业务决策和创新的核心要素&#xff1b;结构化、半结构化等多种类型的数据呈现爆炸式增长&#xff0c;如何高效处理和分析海量数据已经成为关键挑战&#xff0c;结合传统数仓与数据湖优势的湖仓一体&#xff08;Lakehouse&#xff…

解决WSL2占用内存过多问题(Docker on WSL2: VmmemWSL)

解决WSL2占用内存过多问题&#xff08;Docker on WSL2: VmmemWSL&#xff09; 一、问题描述二、问题解决2.1 创建.wslconfig文件2.2 重启wsl2 一、问题描述 安装完WSL2后&#xff0c;又安装了Docker&#xff0c;使用了一段时间&#xff0c;发现电脑变卡&#xff0c;进一步查看…

【VUE异常】el-popconfirm失效,@confirm事件不生效,点击没有任何反应,刷新页面才能点击

el-popconfirm失效&#xff0c;confirm事件不生效&#xff0c;点击没有任何反应&#xff0c;刷新页面才能点击 一、背景描述二、原因分析三、解决方案3.1 方案一&#xff1a;使用onConfirm3.2 方案二&#xff1a;confirm与onConfirm同时使用3.3 方案三&#xff1a;el-popconfir…

【用unity实现100个游戏之12】unity制作一个俯视角2DRPG《类星露谷物语》资源收集游戏demo

文章目录 前言加快编辑器运行速度素材(1)场景人物(2)工具 一、人物移动和动画切换二、走路灰尘粒子效果探究实现 三、树木排序设计方法一方法二 四、绘制拿工具的角色动画五、砍树实现六、存储拾取物品引入Unity 的可序列化字典类 七、实现靠近收获物品自动吸附八、树木被砍掉的…

【详细教程hexo博客搭建】1、从零开始搭建一个能用的博客

1、开始 2.环境与工具准备 本教程主要面对的是Windows用户 操作系统&#xff1a;Windows10NodeGitHexo文本编辑器(强烈推荐VSCODE)GitHub 帐号一个域名&#xff08;强烈推荐买个域名&#xff09;云服务器&#xff08;可选&#xff09; 3.Node的安装 打开Node官网&#xff0…

Error: error:0308010C:digital envelope routines::unsupported

文章目录 1, 问题背景2.解决方法13.解决方法2将 React 脚本升级到 5 以上版本 3.参考资料 1, 问题背景 最近在升级我之前的一个网站的过程中&#xff0c;由于使用了高版本的nodejs v18.0.0报错如下 (undefined) assets/js/styles.1dbb3634.js from Terser Error: error:03080…

LeetCode: 4. Median of Two Sorted Arrays

LeetCode - The Worlds Leading Online Programming Learning Platform 题目大意 给定两个大小为 m 和 n 的有序数组 nums1 和 nums2。 请你找出这两个有序数组的中位数&#xff0c;并且要求算法的时间复杂度为 O(log(m n))。 你可以假设 nums1 和 nums2 不会同时为空。 …

爆破shadow文件密码脚本(完成版)

在之前的博客Python爆破shadow文件密码脚本&#xff08;简化版&#xff09;中我们做了简化版的爆破shadow文件密码的python脚本&#xff0c;接下来在之前代码的基础上改进&#xff1a; import crypt shadow_line"root:$y$j9T$uEgezfJhn7Ov5naU8bzZt.$9qIqkWYObaXajS5iLDA…

Java 时间范围

前端使用Element-ui 时间范围组件 后端注意在Vo里面时间设置String类型不要设置Date类型 XMl组件字段映射成功性

Linux知识点 -- 网络基础(二)-- 应用层

Linux知识点 – 网络基础&#xff08;二&#xff09;-- 应用层 文章目录 Linux知识点 -- 网络基础&#xff08;二&#xff09;-- 应用层一、使用协议来实现一个网络版的计算器1.自定义协议2.守护进程3.使用json来完成序列化 二、HTTP协议1.概念2.HTTP协议请求和响应的报文格式3…

2023/9/18 -- C++/QT

作业 完善登录框 点击登录按钮后&#xff0c;判断账号&#xff08;admin&#xff09;和密码&#xff08;123456&#xff09;是否一致&#xff0c;如果匹配失败&#xff0c;则弹出错误对话框&#xff0c;文本内容“账号密码不匹配&#xff0c;是否重新登录”&#xff0c;给定两…

WebGL 视图矩阵、模型视图矩阵

目录 立方体由三角形构成 视点和视线 视点、观察目标点和上方向 视点&#xff1a; 观察目标点&#xff1a; 上方向&#xff1a; 在WebGL中&#xff0c;观察者的默认状态应该是这样的&#xff1a; 视图矩阵程序&#xff08;LookAtTriangles.js&#xff09; 实际上&…