Tlias智能学习系统
需求:
部门管理:查询、新增、修改、删除
员工管理:查询、新增、修改、删除和文件上传
报表统计
登录认证
日志管理
班级、学员管理(实战内容)
部门管理:
01准备工作
开发规范-开发模式
前后端混合开发缺点:分工不明确、不便管理、难以维护
前后端分离开发:当前最为主流的开发模式:前后端分离
开发流程:
开发规范-Restful风格
REST(REpresentational State Transfer),表述性状态转换,它是一种软件架构风格。
注意:
1.REST是风格,是约定方式,约定不是规定,可以打破
2.描述功能模块通常使用复数形式(加s),表示此类资源,而非单个资源。如:users、books...
Apifox
介绍:Apifox是一款集成了Api文档、Api调试、Api Mock、Api测试的一体化协作平台。
作用:接口文档管理、接口请求测试、mock服务。
官网:Apifox - API 文档、调试、Mock、测试一体化协作平台。拥有接口文档管理、接口调试、Mock、自动化测试等功能,接口开发、测试、联调效率,提升 10 倍。最好用的接口文档管理工具,接口自动化测试工具。
工程搭建:
1.创建SpringBoot工程,并引入Web开发起步依赖、mybatis、mysql驱动、lombok。
2.创建数据库表dept,并在application.yml中配置数据库的基本信息。
CREATE TABLE dept (
id int unsigned PRIMARY KEY AUTO_INCREMENT COMMENT 'ID, 主键',
name varchar(10) NOT NULL UNIQUE COMMENT '部门名称',
create_time datetime DEFAULT NULL COMMENT '创建时间',
update_time datetime DEFAULT NULL COMMENT '修改时间'
) COMMENT '部门表';
INSERT INTO dept VALUES (1,'学工部','2023-09-25 09:47:40','2024-07-25 09:47:40'),
(2,'教研部','2023-09-25 09:47:40','2024-08-09 15:17:04'),
(3,'咨询部','2023-09-25 09:47:40','2024-07-30 21:26:24'),
(4,'就业部','2023-09-25 09:47:40','2024-07-25 09:47:40'),
(5,'人事部','2023-09-25 09:47:40','2024-07-25 09:47:40'),
(6,'行政部','2023-11-30 20:56:37','2024-07-30 20:56:37');
spring:
application:
name: tlias-web-management
#mysql连接配置
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/tlias
username: root
password: 1234
mybatis:
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
3.准备基础代码结构,并引入实体类Dept以及统一的响应结果封装类Result。
package com.itheima.pojo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.time.LocalDateTime;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Dept {
private Integer id;
private String name;
private LocalDateTime createTime;
private LocalDateTime updateTime;
}
package com.itheima.pojo;
import lombok.Data;
import java.io.Serializable;
/**
* 后端统一返回结果
*/
@Data
public class Result {
private Integer code; //编码:1成功,0为失败
private String msg; //错误信息
private Object data; //数据
public static Result success() {
Result result = new Result();
result.code = 1;
result.msg = "success";
return result;
}
public static Result success(Object object) {
Result result = new Result();
result.data = object;
result.code = 1;
result.msg = "success";
return result;
}
public static Result error(String msg) {
Result result = new Result();
result.msg = msg;
result.code = 0;
return result;
}
}
02查询部门
接口开发:
思路分析:明确了查询部门的需求之后,再来梳理一下实现该功能时,三层架构每一层的职责:
Controller:1.接收请求 2.调用service层 3.响应结果
Service:调用Mapper接口方法
Mapper:Selselect id, name, create_time, update_time from dept order by update_time desc ;(SQL)
代码实现:
1). Controller层
在 DeptController
中,增加 list
方法,代码如下:
/**
* 部门管理控制器
*/
@RestController
public class DeptController {
@Autowired
private DeptService deptService;
/**
* 查询部门列表
*/
@RequestMapping("/depts")
public Result list(){
List<Dept> deptList = deptService.findAll();
return Result.success(deptList);
}
}
2). Service层
在 DeptService
中,增加 findAll
方法,代码如下:
public interface DeptService {
/**
* 查询所有部门
*/
public List<Dept> findAll();
}
在 DeptServiceImpl
中,增加 findAll
方法,代码如下:
@Service
public class DeptServiceImpl implements DeptService {
@Autowired
private DeptMapper deptMapper;
public List<Dept> findAll() {
return deptMapper.findAll();
}
}
3). Mapper层
在 DeptMapper
中,增加 findAll
方法,代码如下:
@Mapper
public interface DeptMapper {
/**
* 查询所有部门
*/
@Select("select * from dept")
public List<Dept> findAll();
}
数据封装:
1.问题:
实体类属性名 和 数据库表查询返回的字段一致,mybatis会自动封装。
如果实体类属性名 和 数据库表查询返回的字段名不一致,不能自动封装。
2.解决方案:
手动结果映射:通过@Results以及@Result进行手动结果映射。
package com.itheima.mapper;
import com.itheima.pojo.Dept;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Result;
import org.apache.ibatis.annotations.Results;
import org.apache.ibatis.annotations.Select;
import java.util.List;
@Mapper
public interface DaotMapper {
/**
*查询所有的部门数据
*/
@Results({
@Result(column = "create_time",property = "createTime"),
@Result(column = "update_time",property = "updateTime")
})
@Select("select id, name, create_time, update_time from dept order by update_time desc ;")
List<Dept> findAll();
}
起别名:在SQL语句中,对不一样的列名起别名,别名和实体类属性名一样。
public interface DaotMapper {
/**
*查询所有的部门数据
*/
@Select("select id, name, create_time createTime, update_time updateTime from dept order by update_time desc ;")
List<Dept> findAll();
}
3.开启驼峰(camel)命名:如果字段名和属性名符合驼峰命名规则,mybatis会自动通过驼峰命名规则映射。(推荐方式)
mybatis:
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
#开启驼峰命名映射开关
map-underscore-to-camel-case: true
前后端联调测试
将资料中提供的前端工程文件夹中的压缩包,拷贝到一个没有中文不带空格的目录下,解压。
启动nginx,访问测试:http://localhost:90
前端工程请求服务器的地址为http://localhost:90/api/depts,是如何访问到后端的tomcat服务器的?
(反向代理是一种网络架构,通过代理服务器为后端的服务器做代理,客户端的请求直接代理服务器,然后转发给后端的服务器。(安全,灵活,负载均衡))
Nginx配置文件:
1.location:用于定义匹配路径的规则。
2.^~ /api/:表示精确匹配,即只匹配以/api/开头的路径。
3.rewrite:该指令用于重写匹配到的路径。
4.proxy_pass:该指令用于代理转发,他将匹配到的请求转发给位于后端的指令服务器。
03删除部门
思路分析:
明确了查询部门的需求之后,再来梳理一下实现该功能时,三层架构每一层的职责:
Controller:1.接收请求参数 2.调用service层 3.响应结果
Service:调用Mapper接口方法
Mapper:delete from dept where id = ?;(SQL)
Controller接收参数:
接收请求参数:DELETE /depts?id=8 (简单参数)
方式一:通过原始的HttpServletRequest对象获取请求参数
/**
* 删除部门-方式一:通过原始的HttpServletRequest对象获取请求参数
*/
@DeleteMapping("/depts")
public Result delete(HttpServletRequest request){
String idStr = request.getParameter("id");
int id = Integer.parseInt(idStr);
System.out.println("根据ID删除部门:"+id);
return Result.success();
}
方式二:通过Spring提供的@RequestParam注解,将请求参数绑定给方法形参。
(注意:一旦声明了@RequestParam,该参数在请求时必须传递,如果不传递将会报错,因为默认required为true)
/**
* 删除部门-方式二:通过Spring提供的@RequestParam注解,将请求参数绑定给方法形参。
*/
@DeleteMapping("/depts")
public Result delete(@RequestParam("id") Integer deptId){
System.out.println("根据ID删除部门:"+deptId);
return Result.success();
}
方式三:如果请求参数与形参变量名相同,直接定义方法形参即可接收(省略@RequestParam)
/**
* 删除部门-方式三:如果请求参数与形参变量名相同,直接定义方法形参即可接收(省略@RequestParam)
*/
@DeleteMapping("/depts")
public Result delete(Integer id){
System.out.println("根据ID删除部门:"+id);
return Result.success();
}