企业级开发项目"苍穹外卖"(一)
我不要当骑手,我要当老板~!
---环境搭建---
先下载黑马的资料文件,里面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里面有个可以配置服务器的权重(但是得有两台以上的服务器)
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变量进行加密:
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里导入它的依赖:
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-spring-boot-starter</artifactId>
<version>3.0.2</version>
</dependency>
再在WebMvcConfiguration.java里添加
/**
* 设置静态资源映射
* @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/");
}
/**
* 通过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;
}
里面已经自动编写好了的。
就是添加点注释的意思:@Api添加在控制类上,@ApiOperation,@ApiModel,@ApiModelProperty;
编写Swager注解后就可以在接口文档里看到添加的接口。
---功能开发---
新增员工
在YApi里面查看新增员工的接口:
Server模块里面的Controller层下的EmployeeController类里面编写:
@PostMapping
@ApiOperation("新增员工")
public Result save(@RequestBody EmployeeDTO employeeDTO){
log.info("新增员工:{}",employeeDTO);
employeeService.save(employeeDTO);
return Result.success();
}
然后再点报错的save自动添加到server层,然后在Impl里面实现接口方法:
@Override
public void save(EmployeeDTO employeeDTO) {
Employee employee=new Employee();
// 对象属性拷贝
BeanUtils.copyProperties(employeeDTO,employee);
//设置账号的状态,默认正常状态1表示正常,0表示锁定
employee.setStatus(StatusConstant.ENABLE);
// 设置默认密码
employee.setPassword(DigestUtils.md5DigestAsHex(PasswordConstant.DEFAULT_PASSWORD.getBytes()));
// 设置时间
employee.setUpdateTime(LocalDateTime.now());
employee.setCreateTime(LocalDateTime.now());
// 设置记录人和修改人的id
// TODO 后期修改
employee.setCreateUser(10L);
employee.setUpdateUser(10L);
employeeMapper.insert(employee);
}
EmployeeMapper:
@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类中添加下面代码:
@ExceptionHandler
public Result exceptionHandler(SQLIntegrityConstraintViolationException ex){
// Duplicate entry 'hpan' for key 'employee.idx_username'
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层:
@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里面编写:
<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来操作)
<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:
@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方法
@Override
public Employee getById(Long id) {
Employee employee=employeeMapper.getById(id);
employee.setPassword("******");
return employee;
}
最后再导入分类管理的代码,在资料day2里面的分类管理模块代码,由于跟员工管理的代码差不多,就直接Mapper的导mapper,service的入service,controller的导入controller.不用编写了。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· DeepSeek 开源周回顾「GitHub 热点速览」
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了