七、JavaWeb-后端实战
7.1 准备工作
7.1.1 开发规范
7.1.1.1 开发模式
(1)前后端混合开发,已淘汰
(2)前后端分离开发
7.1.1.2 Restful风格
7.1.2 Apifox
7.1.3 工程搭建
1、先创建空项目project:
2、确定JDK
3、确认maven
4、配置字符集-UTF-8
5、新建SpringBoot工程
依赖: lombok、SpringWeb、MyBatis Framework、MySQL Driver(MySQL驱动)
生成的工程只需要保留:src、xml、iml,其他的可以删掉;
前后端分离开发,static一般不存放静态页面,templates一般不存放模板文件,可以删掉;
使用yml格式的配置文件,properties改成yml
新建数据库tlias,在数据库中
新建Query Console(查询控制台),在里面使用SQL语句建表
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,'学工部','2024-09-25 09:47:40','2024-09-25 09:47:40'),
(2,'教研部','2024-09-25 09:47:40','2024-09-09 15:17:04'),
(3,'咨询部','2024-09-25 09:47:40','2024-09-30 21:26:24'),
(4,'就业部','2024-09-25 09:47:40','2024-09-25 09:47:40'),
(5,'人事部','2024-09-25 09:47:40','2024-09-25 09:47:40'),
(6,'行政部','2024-11-30 20:56:37','2024-09-30 20:56:37');
-- 查询全部的部门
select id, name, create_time, update_time from dept order by update_time desc;
-- 根据ID更新部门数据
update dept set name = '', update_time = '' where id = 1;
yml文件配置信息:
spring:
application:
name: tlias-web-management
# 配置数据库的连接信息
datasource:
url: jdbc:mysql://localhost:3306/tlias
driver-class-name: com.mysql.cj.jdbc.Driver
username: root
password: 1234
# MyBatis的相关配置
mybatis:
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
mapper-locations: classpath:mapper/*xml
7.2 部门管理
7.2.1 列表查询
7.2.1.1 列表查询–接口开发
(1)页面原型
(2)数据库建库建表
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,'学工部','2024-09-25 09:47:40','2024-09-25 09:47:40'),
(2,'教研部','2024-09-25 09:47:40','2024-09-09 15:17:04'),
(3,'咨询部','2024-09-25 09:47:40','2024-09-30 21:26:24'),
(4,'就业部','2024-09-25 09:47:40','2024-09-25 09:47:40'),
(5,'人事部','2024-09-25 09:47:40','2024-09-25 09:47:40'),
(6,'行政部','2024-11-30 20:56:37','2024-09-30 20:56:37');
-- 查询全部的部门
select id, name, create_time, update_time from dept order by update_time desc;
-- 根据ID更新部门数据
update dept set name = '', update_time = '' where id = 1;
(3)思路分析
(4)代码实现:
Controller层:
// @RestController等于@Controller+@RequestBody,
@RequestMapping("/depts")
@RestController
public class DeptController {
@Autowired
private DeptService deptService;
// @RequestMapping(value = "/depts", method = RequestMethod.GET) // method:指定请求方式
// @GetMapping("/depts")
@GetMapping
public Result list() {
System.out.println("查询全部的部门数据");
List<Dept> deptList = deptService.findAll();
return Result.success(deptList);
}
}
Service层:
public interface DeptService {
/**
* 查询所有的部门数据
* @return
*/
List<Dept> findAll();
}
Service实现:
@Service
public class DeptServiceImpl implements DeptService {
@Autowired
private DeptMapper deptMapper;
@Override
public List<Dept> findAll() {
return deptMapper.findAll();
}
}
Mapper层:
@Mapper
public interface DeptMapper {
/**
* 查询所有的部门数据
* @return
*/
@Select("select id, name, create_time, update_time from dept order by update_time desc")
// 方式一
// @Results({
// @Result(column = "create_time", property = "createTime"),
// @Result(column = "update_time", property = "updateTime")
// })
// 方式二
// @Select("select id, name, create_time createTime, update_time updateTime from dept order by update_time")
List<Dept> findAll();
}
结果:
注意到,createTime和updateTime字段返回的数据为null,原因:
三种方式可以解决,推荐使用第三种
开启驼峰命名法,关键字 骆驼 camel
spring:
application:
name: tlias-web-management
#数据库的连接信息
datasource:
url: jdbc:mysql://localhost:3306/tlias
driver-class-name: com.mysql.cj.jdbc.Driver
username: root
password: 1234
#Mybatis相关配置
mybatis:
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
#开启驼峰命名映射开关
map-underscore-to-camel-case: true
7.2.1.2 列表查询–前后端联调
conf文件下为nginx的配置文件:
html文件下为nginx所需要部署的前端项目:
logs文件下为nginx运行的日志:
【nginx.exe】为nginx启动文件,双击一闪而过,在windows环境下则运行成功:
查看nginx配置,地址为localhost,监听90端口:
F12打开开发者工具,并刷新页面:
点击XHR:
7.2.2 删除部门
需求接口文档:
思路分析:
代码实现:
方式一:
方式二:
/**
* 删除部门
* @param deptId
* @return
* 方式二:@RequestParam
* 注意事项:一旦声明了@RequestParam,该参数在请求时必须传递,如果不传递将会报错,默认 required 为 true
*/
@DeleteMapping
public Result deleteById(@RequestParam("id") Integer deptId) {
System.out.println("删除ID为:" + deptId + "部门");
Integer count = deptService.deleteById(deptId);
System.out.println("删除了" + count + "个部门");
return Result.success();
}
报错:
@RequestParam源码:
方式三:
/**
* 删除部门
* @param id
* @return
* 方式三:省略@RequestParam,前端传递的请求参数名与服务端方法形参名一直
*/
@DeleteMapping
public Result deleteById(Integer id) {
System.out.println("删除ID为:" + id + "部门");
Integer count = deptService.deleteById(id);
System.out.println("删除了" + count + "个部门");
return Result.success();
}
Service:
@Service
public class DeptServiceImpl implements DeptService {
@Autowired
private DeptMapper deptMapper;
@Override
public List<Dept> findAll() {
return deptMapper.findAll();
}
@Override
public Integer deleteById(Integer id) {
return deptMapper.delete(id);
}
}
Mapper:
/**
* 根据ID删除部门
* @param id
*/
@Delete("delete from dept where id = #{id}")
Integer delete(Integer id);
7.2.3 新增部门
需求接口文档:
注意:@RequestBody注解使用在方法形参为数据类时,用于将传入的JSON字符转成数据类形式。
7.2.4 查询和修改部门
修改部门的操作包括两个步骤:查询部门和修改部门
7.2.4.1 查询部门
需求接口文档:
/**
* 查询部门(根据ID)
* @param id
*/
@Select("select id, name, create_time, update_time from dept where id = #{id}")
Dept select(Integer id);
7.2.4.2 修改部门
需求接口文档:
7.2.5 日志技术
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<!-- 控制台输出 -->
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度 %logger{50}: 最长50个字符(超出.切割) %msg:日志消息,%n是换行符 -->
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
</encoder>
</appender>
<!-- 日志输出级别 -->
<root level="debug">
<appender-ref ref="STDOUT" />
</root>
</configuration>
package com.itheima;
import org.junit.jupiter.api.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class LogTest {
private static final Logger log = LoggerFactory.getLogger(LogTest.class);
@Test
public void testLog(){
// System.out.println(LocalDateTime.now() + " : 开始计算...");
log.debug("开始计算...");
int sum = 0;
int[] nums = {1, 5, 3, 2, 1, 4, 5, 4, 6, 7, 4, 34, 2, 23};
for (int num : nums) {
sum += num;
}
// System.out.println("计算结果为: "+sum);
// System.out.println(LocalDateTime.now() + "结束计算...");
log.info("计算结果为:" + sum);
log.debug("结束计算...");
}
}
Logger使用的是SLF4J这个接口(即面向接口编程)
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<!-- 控制台输出 -->
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<!--格式化输出:%d 表示日期,%thread 表示线程名,%-5level表示级别从左显示5个字符宽度,%logger显示日志记录器的名称, %msg表示日志消息,%n表示换行符 -->
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50}-%msg%n</pattern>
</encoder>
</appender>
<!-- 系统文件输出 -->
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<!-- 日志文件输出的文件名, %i表示序号,从0开始 -->
<FileNamePattern>D:/tlias-%d{yyyy-MM-dd}-%i.log</FileNamePattern>
<!-- 最多保留的历史日志文件数量 -->
<MaxHistory>30</MaxHistory>
<!-- 最大文件大小,超过这个大小会触发滚动到新文件,默认为 10MB -->
<maxFileSize>10MB</maxFileSize>
</rollingPolicy>
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<!--格式化输出:%d 表示日期,%thread 表示线程名,%-5level表示级别从左显示5个字符宽度,%msg表示日志消息,%n表示换行符 -->
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50}-%msg%n</pattern>
</encoder>
</appender>
<!-- 日志输出级别,此处all或OFF不区分大小写 -->
<root level="ALL">
<appender-ref ref="STDOUT" />
<appender-ref ref="FILE" />
</root>
</configuration>