基于一个案例总结黑马JavaWeb课程
陆陆续续学了快一个多月,总算是把黑马的这个JavaWeb课程给学完了😋
虽然课是叫 JavaWeb,但本质上是大杂烩,开发一个项目基本要用到的知识点都讲了下。
但也正因如此,这个仅40小时的课程缺乏深度(40小时的课,陆陆续续学了一个多月😅)。
而我将根据课程最后的案例(一个标准的增删改查系统)对该课进行总结。
1. 环境准备
该案例使用 SpringBoot 进行开发,所以首先需要创建一个 SpringBoot工程。
该如何创建一个 SpringBoot工程?
不同 IDEA 可能创建方式不一样,以2023版本为例。
注意到这里的 type 是 Maven,什么是 Maven?
在创建 SpringBoot工程时,可以引入需要的起步依赖,
该项目中,我需要用到的是:
- Spring Web
- Lombok
- MySQL Driver
- MyBatis Framework
因为要在项目中使用 MyBatis,所以还需在配置文件application.properties
中引入 MyBatis 的配置信息:
# 驱动类名称
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
# 数据库连接的url
spring.datasource.url=jdbc:mysql://localhost:3306/db01
# 连接数据库的用户名
spring.datasource.username=root
# 连接数据库的密码
spring.datasource.password=123456
# 配置mybatis的日志, 指定输出到控制台
mybatis.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
# 开启mybatis的驼峰命名自动映射开关 a_column ------> aCloumn
mybatis.configuration.map-underscore-to-camel-case=true
接着,就可以在该工程下创建Mapper
包,Service
包,Controller
包以便来储存所要用到的类。
到这里,是不是可以复习下三层架构
的知识了呢。
至此,案例的环境准备工作就完成了。
让我来总结下:
- 因为要使用 SpringBoot 来进行开发,所以要创建 SpringBoot 工程。
- 项目中要用到 MyBatis (这里是利用 SpringBoot 集成 MyBatis 的方式),所以还需在配置文件
application.properties
中引入 MyBatis 的配置信息。 - 根据三层架构的原则,在项目中创建好
Mapper
包,Service
包,Controller
包,并在其中定义好需要用到的类,以便我们后续在对应的类中完成业务代码的编写。
2. 开发规范
现在主流的开发模式为前后端分离模式进行开发。
即前端进行前端部分代码的编写,后端负责后端部分代码的编写。
当然,前后端部分的代码到最后肯定是要进行交互的,前端发起请求时,后端也得响应正确的结果。
所以前后端在进行开发时就需 严格遵守 接口文档进行开发。
可以看到上图的请求和响应中间有一个Restful
,这是个什么东西?
即对前端的请求方式进行了约定,比如:我要进行查询操作,那么发起请求的方式就应该是GET
既然前端的请求都有约定,那后端的响应肯定也是有约束的。
如果不对后端的返回结果的格式有所约束,那前端处理起来可就太过头疼了。
所以一般都会对后端返回数据的格式有所规定,即必须返回某个格式的数据。
在本案例中,采用的是Result
。
3. 开发流程
简单来说就是:
- 看页面原型和接口文档,明确需求
- 思路分析
- 代码实现
- 接口测试与前后端联调
后续进行案例开发时就按照这个开发流程来。
4. 举个例子来演示开发流程与总结框架的使用
接下来正式进入案例的开发。
在该案例中需要开发的有两个功能,即部门管理与员工管理,且每个功能都有着好几个接口。
而这里以部门查询的接口实现为例,来演示下开发流程
与总结框架
的使用。
根据开发流程,要做的第一步就是看页面原型和接口文档,明确需求。
这里先看下整个部门管理功能的页面原型:
接下来进行部门查询接口实现
- 阅读接口文档
刚刚已经看过部门查询的页面原型了,接下来要做的就是阅读接口文档。
- 思路分析
仔细阅读页面原型和接口文档后,要进行的就是思路分析,想一想自己该怎么实现这个接口。
- 代码实现
在代码实现中就涉及到了框架的使用。
要说明的是在黑马 JavaWeb 的整个课程中,几乎没有涉及到任何原理的讲解,只说明了如何去使用。
所以,我也只会从使用的角度进行总结。
该怎么使用框架?通过注解。
controller层
代码:
@Slf4j
@RestController
public class DeptController {
@Autowired
private DeptService deptService;
// @RequestMapping(value = "/depts", method = RequestMethod.GET) //指定请求方式为Get,但这种方式有点繁琐了
@GetMapping("/depts") // 使用 SpringBoot 提供的另一种注解
public Result list() {
log.info("查询全部部门数据");
List<Dept> deptList = deptService.list();
return Result.success(deptList);
}
}
Spring 中的 @RestController
可以看到我在DeptController
上加了注解@RestController
。
首先要说明的是@RestController
结合了@Controller
和@ResponseBody
两个注解的功能。
那@RestController
有啥用,简单来说有两个作用:
- 表明该类可以接收并处理来自客户端的请求,并生成对应的响应(
@Controller
)。 - 让类中方法的返回值转为
JSON
格式的数据(@ResponseBody
)。从
@RestController
的作用中,我们其实可以发现,这不就是为controller层
的类量身定做的么,
因为controller层
的作用就是接收前端发送的请求,为前端响应数据。
@RequestMapping 与 @GetMapping
在方法list()
上我添加了注解 @GetMapping
用于替代@RequestMapping
,也是与前文的开发规范相对应
当然,无论是@GetMapping
还是@RequestMapping
,作用都是在前端发起请求时,调用相对应的方法
在这里就是当前端向地址:http://localhost:8080/depts
发起请求时(可以省略http://localhost:8080
)调用list()
这个方法。
Spring 中的 IOC 与 DI
在我定义的 sevice层的类 private DeptService deptService
上也有一个注解@Autowired
,是干嘛的?
这就涉及到了 Spring 中的 IOC 与 DI,即控制反转与依赖注入。
service层
代码:
@Service
public class DeptServiceImpl implements DeptService {
@Autowired
private DeptMapper deptMapper;
@Override
public List<Dept> list() {
return deptMapper.list(); // 调用Mapper层方法查询所有部门后向controller返回
}
}
mapper层
代码:
@Mapper
public interface DeptMapper {
// 查询所有部门
@Select("select * from dept")
public List<Dept> list();
}
MyBatis 的简单使用
在mapper层
中因为要操作数据库,所以需要使用 MyBatis。
这里是通过注解的方式来编写 SQL 语句。
- 接口测试与前后端联调
代码的实现完成后,要做的就是进行接口的测试以及前后端的联调。
接口测试,可以使用 Postman。
前后端联调:前端工程和后端工程同时启动起来,通过前端工程访问后端工程的接口。
ok,至此,部门查询接口的开发就完成了,本身实现没有什么难度,但重点是通过这个例子,复习总结下 Spring 框架与 MyBatis 框架的使用,以及整个接口开发的流程。
5. 从其他接口的实现中找出不同点
刚刚已经完成了对部门查询接口的开发 ,
而剩下的接口的开发流程大体上来说都是很类似的,所以只需重点关注其中的不同点。
请求参数
在部门查询的接口实现中,前端发送的请求中并未携带请求参数,而通过接口文档可以发现,新增部门与删除部门,前端发送的请求中都有携带请求参数。
删除部门:
新增部门:
所以在接收前端请求时,要考虑如何对参数进行接收。
贴一下controller层
的代码:
@DeleteMapping("/depts/{id}")
public Result delete(@PathVariable Integer id) {
log.info("删除ID为:" + id + " 的部门");
deptService.delete(id);
return Result.success();
}
@PostMapping("/depts")
public Result add(@RequestBody Dept dept) {
log.info("添加名为:" + dept.getName() + " 的部门");
deptService.add(dept);
return Result.success();
}
@PathVariable
用于接收路径参数@RequestBody
用于接收JSON参数
分页插件 PageHelper
不同于部门查询,员工查询的接口要求进行分页条件查询
可以看到请求参数中有page
与pageSize
两个参数,用于进行分页查询。
那么按先前的思路可能就是根据page
与pageSize
两个参数算出起始索引,然后通过 SQL 中的limit
来进行分页查询。
这样做没有问题,但会有一些繁琐,可以借助分页插件 PageHelper 来简化开发。
动态SQL 与 XML 映射文件
完成了对分页查询的实现,再加上条件进行查询。
SQL语句较为复杂,且涉及到条件查询,那我们就得使用动态SQL
,所以在使用 MyBatis框架时,我没有像在部门管理时通过注解的方式来编写 SQL语句,而是使用XML映射文件
的方式。
在这之中我还需注意两点:
可以使用@RequestParam(defaultValue = "1")
的方式,给参数设置默认值。
可以使用@DateTimeFormat(pattern = "yyyy-MM-dd")
的方式,为时间类参数设置格式。
可以发现使用了 PageHelper 插件,就简化了分页查询操作,让我可以把注意力集中在条件查询上。
批量删除
不同于部门管理时的单个删除,删除员工的接口涉及到到批量操作。
。所以我采用list
来接收请求参数:
@DeleteMapping("/emps/{ids}")
public Result delete(@PathVariable List<Integer> ids) {
empService.delete(ids);
return Result.success();
}
对于批量删除的操作,使用动态SQL的foreach
标签:
<delete id="delete">
delete from emp where id in
<foreach collection="ids" item="id" separator="," open="(" close=")">
#{id}
</foreach>
</delete>
6. 写在最后
至此,就完成了对案例的总结。
虽然不是全部,但也对我在学习黑马JavaWeb视频时,一些关键的知识点进行了梳理
在总结中,其实还有两个关键知识点,没有提到
- 文件上传(前端该如何上传文件,后端又该如何进行接收?)
- 登录校验(如何进行用户登录的校验?会话跟踪的三种方案:
Cookie,Seesion,JWT令牌
,过滤器Filter
与拦截器Interceptor
怎么使用?)
因为这两部分相对独立,且内容较多,所以准备等以后再单独进行总结。
黑马 JavaWeb 这个课程,怎么说呢,课还是很不错的,把项目开发中会用到的知识点都串了起来(从前端的知识点 -> Maven -> 框架( 根据 SpringBoot 来进行使用 )-> MySQL -> MyBatis -> 案例学习(加入了文件上传与登录校验)
但正因涉及到的知识点很多,但课时只有40小时,所以讲的很浅,也留下了很多的坑,等着我后面去补,比如:
- 如果不使用 SpringBoot,我如何单独使用 Spring 和 MyBatis 框架进行开发
- 是不是应该再去单独看下专门讲框架的课程,深入学习下。
- JavaWeb 中的 Servlet 没有讲,是不是应该学习一下。
但这种先泛而精的学习,对我而言是效率很高的方式😉
参考资料:黑马程序员JavaWeb开发教程