汕头哪里学网站建设最好,正规投资软件app哪个好,高端网站设计平台,行业网站推广什么意思目录 产品原型与技术选型后端环境搭建Git版本控制IDEA中运行sql脚本文件nginx反向代理和负载均衡完善登录功能 导入接口文档SwaggerSwagger常用注解 产品原型与技术选型
管理端原型图#xff1a; 用户端原型图#xff1a; 餐饮企业内部员工使用。 主要功能有:
模块描述登录… 目录 产品原型与技术选型后端环境搭建Git版本控制IDEA中运行sql脚本文件nginx反向代理和负载均衡完善登录功能 导入接口文档SwaggerSwagger常用注解 产品原型与技术选型
管理端原型图 用户端原型图 餐饮企业内部员工使用。 主要功能有:
模块描述登录/退出内部员工必须登录后,才可以访问系统管理后台员工管理管理员可以在系统后台对员工信息进行管理包含查询、新增、编辑、禁用等功能分类管理主要对当前餐厅经营的 菜品分类 或 套餐分类 进行管理维护 包含查询、新增、修改、删除等功能菜品管理主要维护各个分类下的菜品信息包含查询、新增、修改、删除、启售、停售等功能套餐管理主要维护当前餐厅中的套餐信息包含查询、新增、修改、删除、启售、停售等功能订单管理主要维护用户在移动端下的订单信息包含查询、取消、派送、完成以及订单报表下载等功能数据统计主要完成对餐厅的各类数据统计如营业额、用户数量、订单等
移动端应用主要提供给消费者使用。主要功能有:
模块描述登录/退出用户需要通过微信授权后登录使用小程序进行点餐点餐-菜单在点餐界面需要展示出菜品分类/套餐分类, 并根据当前选择的分类加载其中的菜品信息, 供用户查询选择点餐-购物车用户选中的菜品就会加入用户的购物车, 主要包含 查询购物车、加入购物车、删除购物车、清空购物车等功能订单支付用户选完菜品/套餐后, 可以对购物车菜品进行结算支付, 这时就需要进行订单的支付个人信息在个人中心页面中会展示当前用户的基本信息, 用户可以管理收货地址, 也可以查询历史订单数据 1). 用户层
本项目中在构建系统管理后台的前端页面我们会用到H5、Vue.js、ElementUI、apache echarts(展示图表)等技术。而在构建移动端应用时我们会使用到微信小程序。
2). 网关层
Nginx是一个服务器主要用来作为Http服务器部署静态资源访问性能高。在Nginx中还有两个比较重要的作用 反向代理和负载均衡 在进行项目部署时要实现Tomcat的负载均衡就可以通过Nginx来实现。
3). 应用层
SpringBoot 快速构建Spring项目, 采用 “约定优于配置” 的思想, 简化Spring项目的配置开发。
SpringMVCSpringMVC是spring框架的一个模块springmvc和spring无需通过中间整合层进行整合可以无缝集成。
Spring Task: 由Spring提供的定时任务框架。
httpclient: 主要实现了对http请求的发送。
Spring Cache: 由Spring提供的数据缓存框架
JWT: 用于对应用程序上的用户进行身份验证的标记。
阿里云OSS: 对象存储服务在项目中主要存储文件如图片等。
Swagger 可以自动的帮助开发人员生成接口文档并对接口进行测试。
POI: 封装了对Excel表格的常用操作。
WebSocket: 一种通信网络协议使客户端和服务器之间的数据交换更加简单用于项目的来单、催单功能实现。
4). 数据层
MySQL 关系型数据库, 本项目的核心业务数据都会采用MySQL进行存储。
Redis 基于key-value格式存储的内存数据库, 访问速度快, 经常使用它做缓存。
Mybatis 本项目持久层将会使用Mybatis开发。
pagehelper: 分页插件。
spring data redis: 简化java代码操作Redis的API。
5). 工具
git: 版本控制工具, 在团队协作中, 使用该工具对项目中的代码进行管理。
maven: 项目构建工具。
junit单元测试工具开发人员功能实现完毕后需要通过junit对功能进行单元测试。
postman: 接口测工具模拟用户发起的各类HTTP请求获取对应的响应结果。 后端环境搭建
项目初始的整体结构 对工程的每个模块作用说明
序号名称说明1sky-take-outmaven父工程统一管理依赖版本聚合其他子模块2sky-common子模块存放公共类例如工具类、常量类、异常类等3sky-pojo子模块存放实体类、VO、DTO等4sky-server子模块后端服务存放配置文件、Controller、Service、Mapper等
对项目整体结构了解后接下来我们详细分析上述的每个子模块 sky-common: 模块中存放的是一些公共类可以供其他模块使用
名称说明constant存放相关常量类context存放上下文类enumeration项目的枚举类存储exception存放自定义异常类json处理json转换的类properties存放SpringBoot相关的配置属性类result返回结果类的封装utils常用工具类 sky-pojo: 模块中存放的是一些 entity、DTO、VO
名称说明Entity实体通常和数据库中的表对应DTO数据传输对象通常用于程序中各层之间传递数据VO视图对象为前端展示数据提供的对象POJO普通Java对象只有属性和对应的getter和setter sky-server: 模块中存放的是 配置文件、配置类、拦截器、controller、service、mapper、启动类等
名称说明config存放配置类controller存放controller类interceptor存放拦截器类mapper存放mapper接口service存放service类SkyApplication启动类 Git版本控制
使用Git进行项目代码的版本控制具体操作
1). 创建Git本地仓库 当Idea中出现 说明本地仓库创建成功。
2). 创建Github远程仓库
参考这俩篇博客 Git的下载、安装、配置与使用 在IDEA中将项目上传至github远端仓库
关键是idea中的github用户认证以及本地电脑的SSH keys生成与配置
3). 将本地文件推送到Git远程仓库
1.提交文件至本地仓库 忽略以下类型文件 开始提交 中间出现提醒点击commit
2.添加Git远程仓库地址这里图片以课程老师的gitee为例 3.推送 成功推送至远程仓库 IDEA中运行sql脚本文件
课程老师提供了sql脚本以供建表可以直接在idea里运行脚本在idea项目中配置好数据库连接之后直接右键数据库或者表选中文件路径里的sql脚本运行就行 每张表的说明
序号表名中文名1employee员工表2category分类表3dish菜品表4dish_flavor菜品口味表5setmeal套餐表6setmeal_dish套餐菜品关系表7user用户表8address_book地址表9shopping_cart购物车表10orders订单表11order_detail订单明细表
做完这些启动前端代码nginx修改后端代码application-dev.yml文件中的数据库账号和密码就可以在浏览器80端口访问页面了。 springboot项目里有两个配置文件application.yml和application-dev.yml这两个都是配置文件并且同时生效因为application.yml里有这样一句: spring: profiles: active: dev nginx反向代理和负载均衡
登录功能测试完毕后发现前端请求地址和后端接口地址是不一致的那是如何请求到后端服务的呢 1). nginx反向代理
nginx 反向代理就是将前端发送的动态请求由 nginx 转发到后端服务器。那为什么不直接通过浏览器直接请求后台服务端需要通过nginx反向代理呢 nginx 反向代理的好处 提高访问速度因为nginx本身可以进行缓存如果访问的同一接口并且做了数据缓存nginx就直接可把数据返回不需要真正地访问服务端从而提高访问速度。 进行负载均衡所谓负载均衡,就是把大量的请求按照我们指定的方式均衡的分配给集群中的每台服务器。 保证后端服务安全:因为一般后台服务地址不会暴露所以使用浏览器不能直接访问可以把nginx作为请求访问的入口请求到达nginx后转发到具体的服务中从而保证后端服务的安全。 nginx 反向代理的配置需要在nginx.conf中如下图所示。 proxy_pass该指令是用来设置代理服务器的地址可以是主机名称IP地址加端口号等形式。 如上代码的含义是监听80端口号 然后当我们访问 http://localhost:80/api/…/…这样的接口的时候它会通过 location /api/ {} 这样的反向代理到 http://localhost:8080/admin/上来。
打开nginx-1.20.2\conf打开nginx.conf
# 反向代理,处理管理端发送的请求
location /api/ {proxy_pass http://localhost:8080/admin/;#proxy_pass http://webservers/admin/;
}当在访问http://localhost/api/employee/loginnginx接收到请求后转到http://localhost:8080/admin/故最终的请求地址为http://localhost:8080/admin/employee/login和后台服务的访问地址一致。 2). nginx 负载均衡
当如果服务以集群的方式进行部署时那nginx在转发请求到服务器时就需要做相应的负载均衡。其实负载均衡从本质上来说也是基于反向代理来实现的最终都是转发请求。
nginx 负载均衡的配置方式
upstream webservers{ # upstream如果代理服务器是一组服务器的话我们可以使用upstream指令配置后端服务器组。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;#负载均衡}
}如上代码的含义是监听80端口号 然后当我们访问 http://localhost:80/api/…/…这样的接口的时候它会通过 location /api/ {} 这样的反向代理到 http://webservers/admin根据webservers名称找到一组服务器根据设置的负载均衡策略(默认是轮询)转发到具体的服务器。
注upstream后面的名称可自定义但要上下保持一致。
nginx 负载均衡策略
名称说明轮询默认方式weight权重方式默认为1权重越高被分配的客户端请求就越多ip_hash依据ip分配方式这样每个访客可以固定访问一个后端服务least_conn依据最少连接方式把请求优先分配给连接数少的后端服务url_hash依据url分配方式这样相同的url会被分配到同一个后端服务fair依据响应时间方式响应时间短的服务将会被优先分配
具体配置方式
具体配置方式
轮询
upstream webservers{server 192.168.100.128:8080;server 192.168.100.129:8080;
}weight:
upstream webservers{server 192.168.100.128:8080 weight90;server 192.168.100.129:8080 weight10;
}ip_hash:
upstream webservers{ip_hash;server 192.168.100.128:8080;server 192.168.100.129:8080;
}least_conn:
upstream webservers{least_conn;server 192.168.100.128:8080;server 192.168.100.129:8080;
}url_hash:
upstream webservers{hash request_uri;server 192.168.100.128:8080;server 192.168.100.129:8080;
}fair:
upstream webservers{server 192.168.100.128:8080;server 192.168.100.129:8080;fair;
}完善登录功能
问题员工表中的密码是明文存储安全性太低。 解决思路 将密码加密后存储提高安全性 使用MD5加密方式对明文密码加密 修改数据库中明文密码改为MD5加密后的密文 修改EmployeeServiceImpl.java代码前端提交的密码进行MD5加密后再跟数据库中密码比对
/*** 员工登录** param employeeLoginDTO* return*/public Employee login(EmployeeLoginDTO employeeLoginDTO) {//1、根据用户名查询数据库中的数据//2、处理各种异常情况用户名不存在、密码不对、账号被锁定//.......//密码比对// TODO 后期需要进行md5加密然后再进行比对password DigestUtils.md5DigestAsHex(password.getBytes());if (!password.equals(employee.getPassword())) {//密码错误throw new PasswordErrorException(MessageConstant.PASSWORD_ERROR);}//........//3、返回实体对象return employee;}PS:在EmployeeController的login里我们新建EmployeeLoginVO对象用于返回前端时的代码是这样的
/**
* 登录
*
* param employeeLoginDTO
* return
*/
PostMapping(/login)
ApiOperation(value 员工登录) //描述方法的作用
public ResultEmployeeLoginVO login(RequestBody EmployeeLoginDTO employeeLoginDTO) {log.info(员工登录{}, employeeLoginDTO);Employee employee employeeService.login(employeeLoginDTO);//登录成功后生成jwt令牌MapString, 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);
}其中新建EmployeeLoginVO对象时用到了builder()方法是因为我们在EmployeeLoginVO对象定义时用到了Builder注解
Data
Builder
NoArgsConstructor
AllArgsConstructor
ApiModel(description 员工登录返回的数据格式)
public class EmployeeLoginVO implements Serializable{...
}这样可以节省代码方便我们快速构造对象。 导入接口文档
接下来就要进入到项目的业务开发了而我们的开发方式就是基于当前企业主流的前后端分离开发方式那么这种方式就要求我们之前需要先将接口定义好这样前后端人员才能并行开发就需要将接口文档导入到管理平台为我们后面业务开发做好准备。其实在真实的企业开发中接口设计过程其实是一个非常漫长的过程可能需要多次开会讨论调整甚至在开发的过程中才会发现某些接口定义还需要再调整这种情况其实是非常常见的但是由于项目时间原因所以选择一次性导入所有的接口在开发业务功能过程当中也会带着大家一起来分析一下对应的接口是怎么确定下来的为什么要这样定义。 将课程资料中提供的项目接口导入YApi。YApi现在官网挂了所以使用的是Apifox。在YApi平台创建出两个项目导入到Apifox平台。 Swagger
导入完接口文档之后我们就可以按照接口文档来开发后端代码了之前我们使用postman来测试后端接口但是有的接口可能需要的参数非常多测试效率还是比较低的。而通过Swagger呢就可以帮助我们后端来生成接口文档并且可以进行后端的接口测试是后端开发非常常见的一个技术。
使用Swagger你只需要按照它的规范去定义接口及接口相关的信息就可以做到生成接口文档以及在线接口调试页面。直接使用Swagger也是比较繁琐的knife4j是为Java MVC框架集成Swagger生成Api文档的增强解决方案,前身是swagger-bootstrap-ui。
knife4j的代码我们无需手撸因为都是固定的配置型的代码能知道起什么作用会作相应修改即可
1.pom导入 knife4j 的maven坐标
dependencygroupIdcom.github.xiaoymin/groupIdartifactIdknife4j-spring-boot-starter/artifactIdversion3.0.2/version
/dependency2.在配置类中加入 knife4j 相关配置
WebMvcConfiguration.java
/**
* 通过knife4j生成接口文档
* return
*/
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;
}简单看一下这个代码加入Bean注解表示由Spring创建这个Docket对象并给IOC管理首先创建了一个ApiInfo对象这个其实就是在构建生成的接口文档的一系列信息比如文档的标题、版本、描述然后创建Docket对象指定SWAGGER_2即Swagger版本指定ApiInfo指定生成接口需要扫描的包(及其子包)通过反射来解析这些类和里面的方法最终生成接口文档。
3.设置静态资源映射否则接口文档页面无法访问
同样还是在配置类里面 WebMvcConfiguration.java 把/doc.html和/webjars/**这些请求映射到类路径下面即它帮我们生成接口文档之后这些文件都会放在这个路径下所以发起请求后就需要把它映射到我们真正的这些资源上面去
/*** 设置静态资源映射* param registry*/
protected void addResourceHandlers(ResourceHandlerRegistry registry) {registry.addResourceHandler(/doc.html).addResourceLocations(classpath:/META-INF/resources/);registry.addResourceHandler(/webjars/**).addResourceLocations(classpath:/META-INF/resources/webjars/);
}
//方法名addResourceHandlers不是随便写的因为WebMvcConfiguration继承自WebMvcConfigurationSupport
//所以相当于重写方法写好上述代码之后重启项目进行访问测试接口文档访问路径为 http://ip:port/doc.html — http://localhost:8080/doc.html 接口测试:测试登录功能 思考通过 Swagger 就可以生成接口文档那么我们就不需要 Yapi 或者Apifox等接口管理平台了
1、Yapi 或Apifox是设计阶段使用的工具管理和维护接口
2、Swagger 在开发阶段使用的框架帮助后端开发人员做后端的接口测试 Swagger常用注解
通过注解可以控制生成的接口文档使接口文档拥有更好的可读性常用注解如下
注解说明Api用在类上例如Controller表示对类的说明ApiModel用在类上例如entity、DTO、VO表示对类的说明ApiModelProperty用在属性上描述属性信息ApiOperation用在方法上例如Controller的方法说明方法的用途、作用
接下来使用上述注解生成可读性更好的接口文档在sky-server模块中EmployeeController.java
/*** 员工管理*/
RestController
RequestMapping(/admin/employee)
Slf4j
Api(tags 员工相关接口) //描述类的作用
public class EmployeeController {Autowiredprivate EmployeeService employeeService;Autowiredprivate JwtProperties jwtProperties;/*** 登录** param employeeLoginDTO* return*/PostMapping(/login)ApiOperation(value 员工登录) //描述方法的作用public ResultEmployeeLoginVO login(RequestBody EmployeeLoginDTO employeeLoginDTO) {log.info(员工登录{}, employeeLoginDTO);Employee employee employeeService.login(employeeLoginDTO);//登录成功后生成jwt令牌MapString, 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);}/*** 退出** return*/PostMapping(/logout)ApiOperation(员工退出) //描述方法的作用 value属性也可以不写public ResultString logout() {return Result.success();}}在sky-pojo模块中EmployeeLoginDTO.java
Data
ApiModel(description 员工登录时传递的数据模型)
public class EmployeeLoginDTO implements Serializable {ApiModelProperty(用户名)private String username;ApiModelProperty(密码)private String password;}EmployeeLoginVo.java
Data
Builder
NoArgsConstructor
AllArgsConstructor
ApiModel(description 员工登录返回的数据格式)
public class EmployeeLoginVO implements Serializable {ApiModelProperty(主键值)private Long id;ApiModelProperty(用户名)private String userName;ApiModelProperty(姓名)private String name;ApiModelProperty(jwt令牌)private String token;}重启服务访问http://localhost:8080/doc.html,可以看到接口都变成了注解中的说明接口参数也有对应描述信息。