Day_1

1. 环境搭建

技术选型

后端项目结构

sky-take-out

maven父工程,统一管理依赖版本,聚合其他子模块

sky-common

子模块,存放公共类,例如:工具类、常量类、异常类等

sky-pojo

子模块,存放实体类、VODTO

sky-server

子模块,配置文件、ControllerServiceMapper

sky-common

存放的是一些公共类,可以供其他模块使用

sky-pojo

存放的是一些 entityDTOVO

sky-server

存放的是 配置文件、配置类、拦截器、controllerservicemapper、启动类等

数据库

参考数据库设计文档

前后端联调

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

前端请求地址:http://localhost/api/employee/login

后端接口地址:http://localhost:8080/admin/employee/login

nginx 反向代理

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

nginx 反向代理的好处:

  1. 提高访问速度,nginx可以进行缓存
  2. 进行负载均衡,针对分布式系统
  3. 保证后端服务安全,不会对外公开自己的服务调用接口

配置方式

在文件 nginx.conf

反向代理的配置方式:

server{listen 80;server_name localhost;location /api/ {proxy_pass   http://localhost:8080/admin/;  #反向代理}}

nginx 负载均衡的配置方式:

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/;  #负载均衡 默认为轮询}}

 2. 登录功能

员工表中的密码是明文存储,安全性太低,采用 MD5 加密格式

拦截器配置

需求:在调用用户登录接口的时候不需要进行 jwtToken 认证,其他接口都需要进行认证

拦截器对动态方法进行拦截

登录Controller

对于新登录的用户,生成一个 jwt 令牌

@PostMapping("/login")
@ApiOperation(value = "员工登录")
public Result<EmployeeLoginVO> login(@RequestBody EmployeeLoginDTO employeeLoginDTO) {log.info("员工登录:{}", employeeLoginDTO);Employee employee = employeeService.login(employeeLoginDTO);//登录成功后,生成jwt令牌Map<String, Object> claims = new HashMap<>();claims.put(JwtClaimsConstant.EMP_ID, employee.getId());String token = JwtUtil.createJWT(jwtProperties.getAdminSecretKey(),jwtProperties.getAdminTtl(),claims);EmployeeLoginVO employeeLoginVO = EmployeeLoginVO.builder().id(employee.getId()).userName(employee.getUsername()).name(employee.getName()).token(token).build();return Result.success(employeeLoginVO);
}

登录service

因为数据库里存的是进行 md5 加密后的信息,在进行密码对比的时候,需要将前端传入的明文密码转为 md5 后再进行对比

 3. Swagger

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

<dependency><groupId>com.github.xiaoymin</groupId><artifactId>knife4j-spring-boot-starter</artifactId><version>3.0.2</version>
</dependency>

使用方式

1. 导入 knife4j maven坐标

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

WebMvcConfiguration.java

@Bean
public Docket docket() {log.info("准备生产接口文档");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;
}

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

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/");
}

4. 访问

接口文档访问路径为 http://ip:port/doc.html

常用注解

注解

说明

@Api

用在类上,例如Controller,表示对类的说明

@ApiModel

用在类上,例如entityDTOVO

@ApiModelProperty

用在属性上,描述属性信息

@ApiOperation

用在方法上,例如Controller的方法,说明方法的用途、作用


4. 员工管理 

开发都是采用三层结构(MVC模式),具体查看源码

代码开发:

1. 设计接受前端传入的 DTO 

2. 在 Controller 定义执行方法

3. 在 Service,ServiceImpl 中进行实现方法逻辑

4. 在 Mapper 层进行对数据库的调用查询

5. Controller 返回前端需要的数据类型

新增员工

正常采用三层结构实现

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

程序存在问题

1. 在出现同样的 username 的时候,系统会报错;

该异常应被全局异常处理器处理

@ExceptionHandler
public Result exceptionHandler(SQLIntegrityConstraintViolationException ex) {//错误内容: Duplicate entry 'zhangsan' for key 'idx_username'final String message = ex.getMessage();if(message.contains("Duplicate entry")) {String[] split = message.split(" ");String username = split[2];String msg = username + MessageConstant.ALREADY_EXISTS;return Result.error(msg);}else {return Result.error(MessageConstant.UNKNOWN_ERROR);}
}

2. 当前登录用户的 id 如何存储

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

在 sky-common 中已经封装为 BaseContext 类

员工分页查询

分页查询使用使用 mybatis 的分页插件 PageHelper 来简化分页代码的开发。

底层基于 mybatis 的拦截器实现,在 sql 语句后面进行拼接 limit

代码完善

日期时间在前端的显示结果不是我们想要的

解决方法:

1. 在属性上加入注解,对日期进行格式化

可以实现日期的序列化,但是只能实现这一个属性的序列化。 不推荐

2.  WebMvcConfiguration 中扩展Spring MVC的消息转换器,统一对日期类型进行格式化

protected void extendMessageConverters(List<HttpMessageConverter<?>> converters) {//自己创建一个消息转换器MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();// 为消息转换器 设置一个对象转换器,可以将java对象序列化为json数据converter.setObjectMapper(new JacksonObjectMapper());//将自己的消息转换器加入到容器里, 默认是放在最后一个// 0 -> 就是把这个消息转换器放在前面converters.add(0, converter);
}

启用禁用员工账号

需要一个 update 数据库的方法

在 EmployeeMapper.xml 编写 SQL

<update id="update" parameterType="Employee">update employee<set><if test="name != null and name != ''" >name = #{name},</if><if test="username != null and username != ''" >username = #{username},</if><if test="sex != null and sex != ''" >sex = #{sex},</if><if test="password != null and password != ''" >password = #{password},</if><if test="phone != null and phone != ''" >phone = #{phone},</if><if test="idNumber != null and idNumber != ''" >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>

编辑员工信息

需要一个查询员工信息的接口,和上一个的修改员工信息的接口


5. 分类模块功能

思路与员工管理的一致,做着基本的crud

注:

在删除分类的时候,要求其下面没有挂载任何内容才可以


6. 公共字段自动填充

针对业务表里的公共字段进行维护

序号

字段名

含义

数据类型

1

create_time

创建时间

datetime

2

create_user

创建人id

bigint

3

update_time

修改时间

datetime

4

update_user

修改人id

bigint

实现思路

技术:注解、AOP、反射

思路:

1.自定义注解 AutoFill,用于标识需要进行公共字段自动填充的方法

2.自定义切面类 AutoFillAspect,统一拦截加入了 AutoFill 注解的方法,通过反射为公共字段赋值

3.在 Mapper 的方法上加入 AutoFill 注解

开发

自定义注解 AutoFill

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface AutoFill {//数据库操作类型: update insertOperationType value();}

自定义切面类 AutoFillAspect

@Aspect
@Component
@Slf4j
public class AutoFillAspect {/*** 指定切入点*/@Pointcut("execution(* com.sky.mapper.*.*(..)) &&             @annotation(com.sky.annotation.AutoFill)")public void autoFillPointCut(){}/*** 前置通知,在通知中进行公共字段的赋值*/@Before("autoFillPointCut()")public void autoFill(JoinPoint joinPoint) {log.info("开始进行公共字段的填充");// 在这里实现逻辑}}

实现逻辑:

1.  获取到当前被拦截到的方法的数据库操作类型

//获取到方法签名对象
MethodSignature signature = (MethodSignature)joinPoint.getSignature(); 
//获取方法上的注解对象
AutoFill autoFill = signature.getMethod().getAnnotation(AutoFill.class); 
// 获取到数据库的操作类型
OperationType operationType = autoFill.value();  

2. 获取到被拦截的方法的参数(实体对象)  这里约定: 参数里面的实体对象为第一个参数

Object[] args = joinPoint.getArgs();
if(args == null || args.length == 0) {return;
}
Object entity = args[0];

3. 获取赋值的数据

LocalDateTime now = LocalDateTime.now();
Long currentId = BaseContext.getCurrentId();

4. 通过反射来赋值

if(operationType == OperationType.INSERT) {//给4个公共字段赋值try {// 获取创建时间方法Method setCreateTime = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_CREATE_TIME,LocalDateTime.class);// 获取创建人方法Method setCreateUser =     entity.getClass().getDeclaredMethod(AutoFillConstant.SET_CREATE_USER, Long.class);// 获取修改时间方法Method setUpdateTime = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_TIME, LocalDateTime.class);// 获取修改人方法Method setUpdateUser = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_USER, Long.class);// 赋值操作// 创建时间赋值setCreateTime.invoke(entity, now);// 创建人赋值setCreateUser.invoke(entity, currentId);// 修改时间赋值setUpdateTime.invoke(entity, now);// 修改人赋值setUpdateUser.invoke(entity, currentId);} catch (Exception e) {e.printStackTrace();}
}else if(operationType == OperationType.UPDATE) {//给2个公共字段赋值try {// 获取修改时间方法Method setUpdateTime =     entity.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_TIME, LocalDateTime.class);// 获取修改人方法Method setUpdateUser = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_USER, Long.class);// 赋值操作// 修改时间赋值setUpdateTime.invoke(entity, now);// 修改人赋值setUpdateUser.invoke(entity, currentId);} catch (Exception e) {throw new RuntimeException(e);}
}else {// 既不是新增又不是修改throw new RuntimeException(MessageConstant.UNKNOWN_ERROR);
}

5. Mapper接口的方法上加入 AutoFill 注解

@AutoFill(OperationType.INSERT@AutoFill(OperationType.UPDATE)

6. 去掉业务层这个重复的代码

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

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

相关文章

node.js对数据库的操作 之 query(查询)与pool(连接池)

一、Query&#xff08;查询&#xff09; &#xff08;1&#xff09;意义 query是指向数据库发送的一个命令或请求&#xff0c;以检索、更新、插入或删除数据。它是一个具体的SQL语句或NoSQL命令&#xff0c;用于从数据库中获取或修改数据。 &#xff08;2&#xff09;用途 …

4个可将 iPhone iPad iPod 修复至正常状态的 iOS 系统恢复软件

许多iOS用户对操作系统问题感到恐慌&#xff0c;例如iPhone卡在恢复模式、白屏死机、黑屏死机、iOS系统损坏、iTunes连接屏幕、iPhone数据丢失等。这些状态通常很无聊&#xff0c;因为您无法使用 iPhone 执行任何操作。 4个可将 iPhone iPad iPod 修复至正常状态的 iOS 系统恢复…

一键自动化博客发布工具,用过的人都说好(segmentfault篇)

segmentfault是我在这些平台中看过界面最为简洁的博客平台了。 今天就以segmentfault为例&#xff0c;讲讲在blog-auto-publishing-tools中的实现原理。 前提条件 前提条件当然是先下载 blog-auto-publishing-tools这个博客自动发布工具,地址如下&#xff1a;https://github…

win中python中OpenCV使用cv2.imshow()报错的解决办法

1. 问题 cv2.error: OpenCV(4.9.0) D:\a\opencv-python\opencv-python\opencv\modules\highgui\src\window.cpp:1272: error: (-2:Unspecified error) The function is not implemented. Rebuild the library with Windows, GTK 2.x or Cocoa support. If you are on Ubuntu o…

leetcode45.跳跃游戏||

问题描述&#xff1a; 给定一个长度为 n 的 0 索引整数数组 nums。初始位置为 nums[0]。 每个元素 nums[i] 表示从索引 i 向前跳转的最大长度。换句话说&#xff0c;如果你在 nums[i] 处&#xff0c;你可以跳转到任意 nums[i j] 处: 0 < j < nums[i] i j < n 返…

KNOWLEDGE DISTILLATION BASED ON TRANSFORMED TEACHER MATCHING

摘要 温度标度作为logit匹配和概率分布匹配的bridge技术&#xff0c;在知识蒸馏&#xff08;KD&#xff09;中起着至关重要的作用。传统上&#xff0c;在蒸馏中&#xff0c;温度标度适用于教师的logits和学生的logits。在本文中&#xff0c;受到最近一些研究成果的启发&#x…

解锁程序员高效编程之谜:软件工具、编辑器与插件的秘密武器大公开!

程序员如何提高编程效率&#xff1f; 程序员提高编程效率是一个多方面的过程&#xff0c;涉及技能提升、工具使用、时间管理以及工作习惯等多个方面。以下是一些建议&#xff0c;帮助程序员提高编程效率&#xff1a; 1. 选择适合的工具 使用高效的代码编辑器或集成开发环境&…

高防护皮带机巡检机器人:适应恶劣环境的智能助手

在众多工业领域中&#xff0c;皮带机作为一种重要的物料输送设备&#xff0c;广泛应用于发电厂、煤栈等场所。然而&#xff0c;长期以来&#xff0c;皮带机的巡检工作一直依赖人工&#xff0c;存在着劳动强度大、检测效率低、安全性差等问题。为了解决这些痛点&#xff0c;皮带…

Redis 渐进式遍历 -- scan

前言 keys 可以一次性把 Redis 中的所有 key 都获取到&#xff0c;但这个操作比较危险&#xff0c;一次性获取所有的key 很容易会导致 Redis 阻塞。 而通过渐进式遍历&#xff08;不是一个命令就将所有的 key 值拿到&#xff0c;而是每执行一次命令只获取其中的一小部分&#x…

我独自升级崛起在哪下载 我独自升级电脑PC端下载教程分享

将于5月8日在全球舞台闪亮登场的动作角色扮演游戏《我独自升级崛起》&#xff0c;灵感源自同名热门动画与网络漫画&#xff0c;承诺为充满激情的游戏玩家群体带来一场集深度探索与广阔体验于一身的奇幻旅程。该游戏以独特的网络武侠世界观为基底&#xff0c;展现了一位普通人踏…

CPU炼丹——YOLOv5s

1.Anaconda安装与配置 1.1安装与配置 Anaconda3的安装看下面的教程&#xff1a; 最新Anaconda3的安装配置及使用教程&#xff08;详细过程&#xff09;http://t.csdnimg.cn/yygXD&#xff0c;接上面文章下载后&#xff0c;配置环境变量的时候记得在原来你装的Python更下面添…

【项目】高并发内存池实现(化简版tcmalloc)

前言 因为偶然的机会&#xff0c;我通过同学那里知道这个google有一个开源项目tcmalloc&#xff0c;他讲的头头是道&#xff0c;而我也对其非常感兴趣。 这个tcmalloc呢&#xff0c;全称Thread-Caching Malloc&#xff0c;通过名字就能看出跟线程相关&#xff0c;也确实如此&am…

Spring Data JPA的一对一、LazyInitializationException异常、一对多、多对多操作

Spring Data JPA系列 1、SpringBoot集成JPA及基本使用 2、Spring Data JPA Criteria查询、部分字段查询 3、Spring Data JPA数据批量插入、批量更新真的用对了吗 4、Spring Data JPA的一对一、LazyInitializationException异常、一对多、多对多操作 前言 通过前三篇Sprin…

[SaaS]建筑领域的sd应用

AirchiDesignhttp://www.aiarchi.art/#/建筑学长——千万建筑师的资源库和AI绘图创作平台建筑学长官网,为青年设计师建立的线上资源共享及AI绘图创作渲染平台,免费提供海量设计案例、CAD图纸、SU模型、PS素材、软件插件下载,提供丰富的设计软件教学与灵感参考素材图库。https:/…

扩展学习|一文读懂知识图谱

一、知识图谱的技术实现流程及相关应用 文献来源&#xff1a;曹倩,赵一鸣.知识图谱的技术实现流程及相关应用[J].情报理论与实践,2015, 38(12):127-132. &#xff08;一&#xff09;知识图谱的特征及功能 知识图谱是为了适应新的网络信息环境而产生的一种语义知识组织和服务的方…

常用六大加密软件排行榜|好用加密文件软件分享

为了保障数据安全&#xff0c;越来越多的企业开始使用文件加密软件。哪款加密软件适合企业哪些办公场景呢&#xff1f; 今天就给大家推荐一下文件加密软件排行榜的前六名&#xff1a; 1.域智盾 这款软件专为企业和政府机构设计&#xff0c;提供全面的文件保护解决方案。 点…

SOLIDWORKS Electrical电气智能零部件的运用

电气2D向电气3D转型&#xff0c;3D模型无疑是重中之重&#xff0c;精准、正确的3D模型有利于电线长度、空间大小、耗材的计算。而线槽、导轨因为要根据实际情况裁剪&#xff0c;所以即使同一规格的线槽、导轨&#xff0c;在装配时也得根据实际情况&#xff0c;修改长度&#xf…

一文带你了解多数企业系统都在用的 RBAC 权限管理策略

前言 哈喽你好呀&#xff0c;我是 嘟老板&#xff0c;今天我们来聊聊几乎所有企业系统都离不开的 权限管理&#xff0c;大家平时在做项目开发的时候&#xff0c;有没有留意过权限这块的设计呢&#xff1f;都是怎样实现的呢&#xff1f;如果现在脑子里对于这块儿不够清晰&#…

【爬虫】爬取A股数据写入数据库(一)

1. 对东方财富官网的分析 步骤&#xff1a; 通过刷新网页&#xff0c;点击等操作&#xff0c;我们发现https://datacenter-web.eastmoney.com/api/data/v1/get?请求后面带着一些参数即可以获取到相应数据。我们使用python来模拟这个请求即可。 我们以如下选择的页面为切入点…

经典的设计模式和Python示例(一)

目录 一、工厂模式&#xff08;Factory Pattern&#xff09; 二、单例模式&#xff08;Singleton Pattern&#xff09; 三、观察者模式&#xff08;Observer Pattern&#xff09; 一、工厂模式&#xff08;Factory Pattern&#xff09; 工厂模式&#xff08;Factory Pattern…