项目日志 苍穹外卖 企业级开发项目《苍穹外卖》(一) 何平安 2024-02-04 2024-08-03 我不要当骑手,我要当老板~!
—环境搭建— 先下载黑马的资料文件,里面day1的前端代码文件文件夹将其复制到一个全英文路径的地方,然后运行里面的nginx.exe ,浏览器输入localhost如果有苍穹外卖的界面说明就成功了。
IDEA打开后端代码文件里面的sky-take-out,里面已经搭建好了三个模块及各个模块的内容。
git环境搭建
创建git仓库:VCS栏里找到创建git仓库,路径就选择sky-take-out,没有下载git的话就去先下载:https://registry.npmmirror.com/-/binary/git-for-windows/v2.40.0.windows.1/Git-2.40.0-64-bit.exe
我的博客的下一文章就有git的详细教学
安装教程:Git 详细安装教程(详解 Git 安装过程的每一个步骤)_git安装_mukes的博客-CSDN博客 或git的安装与配置(详细) - 知乎 (zhihu.com) ,
IDEA配置git教程:IDEA配置git详细步骤_idea git config_字节小龙的博客-CSDN博客 ,github加速器推荐选择网易的UU加速器,或者用国内的gitee(码云)
然后点击提交(ctrl+k),选中全部文件然后下面写注释苍穹外卖,提交即可。这是提交到本地git仓库
创建远程gitee仓库:工作台 - Gitee.com ,先创建一个账号然后点击创建仓库(新建仓库 - Gitee.com ),名字就是sky-take-out吧,定义为私有。然后再复制,回到IDEA,找到git里面的推送(一个箭头符号),点击左边下划线部分,输入刚刚复制的url,然后点击仍然推送。
数据环境搭建
数据库文件下载:https://picture-hepingan.oss-cn-hangzhou.aliyuncs.com/sky.sql,再在resources里面配置文件里面配置和数据库密码等信息。
前后端联调
运行Maven生命周期的compile,然后再运行server模块里面的运行类。打开localhost网址(默认端口号为80),数据库里面有个管理的账号:admin,密码123456,输入并登录。可以先去调试下EmpControllerImpl熟悉下项目。
Nginx反向代理
将前端发送的动态请求由nignx转发到后端服务器。好处:提高访问速度,进行负载均衡,保证后端安全。
nginx负载均衡策略:
nignx.conf里面有个可以配置服务器的权重(但是得有两台以上的服务器)
1 2 3 4 upstream webservers{ server 127.0 .0 .1 :8080 weight=90 ; #server 127.0 .0 .1 :8088 weight=10 ; }
登录系统的完善
为了增加安全性,使用md5进行加密处理,把一个明文加密处理,但是不能反向回解,所以是单向的。比如将admin的密码123456进行加密就是:e10adc3949ba59abbe56e057f20f883e,将其复制到employee数据库里的password,然后再在EmployeeServiceImpl里的//TODD 注释下将password变量进行加密:
1 password =DigestUtils.md5DigestAsHex(password.getBytes());
导入接口文档
使用前后端分离的方式开发。找到资料里面的两个json格式接口文件,再在YAPI官网(https://yapi.pro/)里导入这个两个接口,要分别新建两个项目,再在项目里面的数据管理里选择json格式带入。
Swagger
Swagger 是一个规范和完整的框架,用于生成、描述、调用和可视化 RESTful 风格的 Web 服务(https://swagger.io/)。 它的主要作用是:
使得前后端分离开发更加方便,有利于团队协作
接口的文档在线自动生成,降低后端开发人员编写接口文档的负担
功能测试
Spring已经将Swagger纳入自身的标准,建立了Spring-swagger项目,现在叫Springfox。通过在项目中引入Springfox ,即可非常简单快捷的使用Swagger。
直接使用Knife4j(为Java MVC框架集成Swagger生成Api文档的增强解决方案),里面封装了Swagger的,在pom.xml里导入它的依赖:
1 2 3 4 5 <dependency> <groupId>com.github.xiaoymin</groupId> <artifactId>knife4j-spring-boot-starter</artifactId> <version>3.0 .2 </version> </dependency>
再在WebMvcConfiguration.java里添加
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 protected void addResourceHandlers (ResourceHandlerRegistry registry) { registry.addResourceHandler("/doc.html" ).addResourceLocations("classpath:/META-INF/resources/" ); registry.addResourceHandler("/webjars/**" ).addResourceLocations("classpath:/META-INF/resources/webjars/" ); } @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; }
里面已经自动编写好了的。
就是添加点注释的意思:@Api添加在控制类上,@ApiOperation,@ApiModel,@ApiModelProperty;
编写Swager注解后就可以在接口文档里看到添加的接口。
—功能开发— 新增员工 在YApi里面查看新增员工的接口:
Server模块里面的Controller层下的EmployeeController类里面编写:
1 2 3 4 5 6 7 8 @PostMapping @ApiOperation("新增员工") public Result save (@RequestBody EmployeeDTO employeeDTO) { log.info("新增员工:{}" ,employeeDTO); employeeService.save(employeeDTO); return Result.success(); }
然后再点报错的save自动添加到server层,然后在Impl里面实现接口方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 @Override public void save (EmployeeDTO employeeDTO) { Employee employee=new Employee (); BeanUtils.copyProperties(employeeDTO,employee); employee.setStatus(StatusConstant.ENABLE); employee.setPassword(DigestUtils.md5DigestAsHex(PasswordConstant.DEFAULT_PASSWORD.getBytes())); employee.setUpdateTime(LocalDateTime.now()); employee.setCreateTime(LocalDateTime.now()); employee.setCreateUser(10L ); employee.setUpdateUser(10L ); employeeMapper.insert(employee); }
EmployeeMapper:
1 2 3 @Insert("insert into employee (name, username, password, phone, sex, id_number, create_time, update_time, create_user, update_user,status) " + "values(#{name},#{username},#{password},#{phone},#{sex},#{idNumber},#{createTime},#{updateTime},#{createUser},#{updateUser},#{status})") void insert (Employee employee) ;
测试连接
打开苍穹外卖项目接口文档 ,先去员工登录接口测试拿到一个JWT令牌,然后再在文档管理的全局参数配置里添加名为token的值为JWT令牌的参数,然后再去测试添加员工的接口。记得输入规定的内容,比如idNumber就为18位身份证号。phone为11位。如果报401就是令牌过期了,记得重新申请!
代码补充
如果添加一个相同的员工名字就会报500的错误,这时就需要给用户返回错误信息,在GobleExceptionHandler类中添加下面代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 @ExceptionHandler public Result exceptionHandler (SQLIntegrityConstraintViolationException ex) { String message=ex.getMessage(); if (message.contains("Duplicate entry" )){ String[] split=message.split(" " ); String username=split[2 ]; String msg=username+ "已存在" ; return Result.error(msg); }else { return Result.error(MessageConstant.UNKNOWN_ERROR); } }
然后测试接口文档就会报:
完善操作人的ID:就是save里面的10L,使用Thread.currentThread().getId()获取当前线程的ID,输出后每次请求的ID都不一样,这样可以验证每次操作的线程都不一样,在JWT令牌添加模块里面使用BaseContext.setCurrentId(empId)将ID存储到一个空间里去,然后再将10L替换成BaseContext.getCurrentId()取出来。
员工分页查询 老样子Controller层–>Service层–>Mapper层
Controller层:
1 2 3 4 5 6 7 @GetMapping("/page") @ApiOperation("分页查询") public Result<PageResult> page (EmployeePageQueryDTO employeePageQueryDTO) { log.info("分页查询:{}" ,employeePageQueryDTO); PageResult pageResult=employeeService.page(employeePageQueryDTO); return Result.success(pageResult); }
pom.xml文件里面添加分页查询的依赖,源文件已经配置好了。
再在ServiceImpl里面编写:PageHelper.startPage(employeePageQueryDTO.getPage(),employeePageQueryDTO.getPageSize());
由于SQL语句比较复杂要用到模糊查询,所以就在xml里面编写:
1 2 3 4 5 6 7 8 9 <select id ="pageQuery" resultType ="com.sky.entity.Employee" > select * from sky_take_out.employee <where > <if test ="name != null and name != ''" > name like concat('%', #{name}, '%') </if > </where > order by create_time desc </select >
编辑,根据ID查询员工 补充启动警用员工(也顺便弄出编辑员工的模块):P0ST的Controller–>update的SQL:(根据ID来操作)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 <update id ="update" > update sky_take_out.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" > idNumber=#{idNumber} </if > <if test ="updateTime !=null" > updateTime=#{updateTime} </if > <if test ="updateUser !=null" > updateUser=#{updateUser} </if > <if test ="status !=null" > status=#{status} </if > </set > where id =#{id} </update >
根据id查询员工和编辑员工:
还是根据接口文档来编写,不多说,直接上代码:
编辑员工信息的ServiceImpl:
1 2 3 4 5 6 7 8 9 @Override public void update (EmployeeDTO employeeDTO) { Employee employee=new Employee (); BeanUtils.copyProperties(employeeDTO,employee); employee.setUpdateTime(LocalDateTime.now()); employee.setUpdateUser(BaseContext.getCurrentId()); employeeMapper.update(employee); }
这里是直接调用刚刚启动禁用员工的SQL语句
根据ID查询的ServiceImpl层:加一个密码加密的set方法
1 2 3 4 5 6 @Override public Employee getById (Long id) { Employee employee=employeeMapper.getById(id); employee.setPassword("******" ); return employee; }
最后再导入分类管理的代码,在资料day2里面的分类管理模块代码,由于跟员工管理的代码差不多,就直接Mapper的导mapper,service的入service,controller的导入controller.不用编写了。