web项目工程搭建、Result封装类、部门功能的增删改查和日志技术Logback
工程搭建第一步1.检查maven版本和JDK版本(这里我们采用17)和字符集版本(UTF-8)检查mavenJDK版本检查字符集2.创建SpringBoot工程3.引入web开发起步依赖lombok驱动(Spring Boot版本自行选择)spring websql驱动(mysql和mybatis)第二步1.配置yml文件#Spring Boot项目名字 spring: application: name:项目名字#配置数据库 datasource: #配置数据库连接池类型(德鲁伊或追光者) type: com.alibaba.druid.pool.DruidDataSource url: jdbc:mysql://localhost:3306/连接的数据库名字driver-class-name: com.mysql.cj.jdbc.Driver username:数据库用户名password:数据库密码#配置MyBatis mybatis: #配置映射文件 mapper-locations: classpath:mapper/*.xml #配置实体类包名 configuration: log-impl: org.apache.ibatis.logging.stdout.StdOutImpl2.创建数据库-- 创建部门表 dept 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);第三步准备基础代码建立三层架构以及实体类包pojo0.注解注意事项Controller 层本身就是控制器类直接在类上使用RestController/Controller无需接口。Service 层接口只定义方法规范不能加Service。实现类上必须加ServiceSpring 才会扫描并实例化这个实现类交给容器管理。Mapper 层DAO接口上直接加Mapper或启动类MapperScan即可。由 MyBatis 的动态代理机制自动生成接口的代理实现类所以我们不用手动写实现类也不用在别的地方加注解。1.创建实体类Dept和Result2.创建Mapper层接口3.创建Service层的接口以及其实现类(一般实现类要放在Impl包下面)特别提醒所有三层架构的注解都必须加载其实现类的头上但由于Mapper利用了动态代理来创建一个虚拟的实现类并且Controller本身就是只有类所以不需要特别强调Service多多留意4.创建Controller层的类Result封装类(将返回给前端的结果封装为一个Result类)package com.itheima.pojo; import lombok.Data; 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; return result; }#方法重载---成功返回封装的对象public static Result success(Object object) { Result result new Result();result.data object;---返回的对象数据result.code 1;---默认返回1为成功return result; } public static Result error(String msg) { Result result new Result(); result.msg msg;result.code 0;---默认返回0为失败return result; } }部门功能1.查询部门(1)需求分析根据接口文档分析需求这点是非常重要的一般就是分析基本的信息请求的参数响应的数据[1]分析基本信息[2]分析请求参数因为是查询所有并没有特殊查询所以不需要带参数[3]分析我们需要给前端响应回去的数据(2)分析三层架构的职责Mapper层的sql语句我们可以现在数据库中编写并且测试比如我们这个部门的要求用如下sql语句即可-- 查询全部部门 select id, name, create_time, update_time from dept order by update_time desc;之后Mapper层获取数据我们的Service通过调用Mapper的接口方法拿回数据我们的Controller层调用Service层的方法拿到数据最后返回给前端(3)编写三层架构[1]编写Controller层RestController public class DeptController { Autowired private DeptService deptService;--这里调用的Service层的方法不要忘记DI依赖注入和IOC控制反转RequestMapping(value/deptsmethod RequestMethod.GET)--这里的请求访问路径参考接口文档RequestMapping中限定访问类型为GetRequestMethod是一个枚举类型同样的你可以直接将RequestMapping替换为GetMappingpublic Result list(){--这个方法返回的是Result数据也就是响应给前端的数据System.out.println(查询全部部门数据); ListDept deptList deptService.findAll();--调用Service层方法这个findAll()返回的是所有的部门数据所以我们封装在List集合中。return Result.success(deptList);--返回结果其实就是我们的Result封装类的方法成功返回并且封装数据} }[2]编写Service层这里唯一需要注意的就是Service要加在实现类而非接口上因为控制反转是将类实例化的权限放在了容器里而接口是无法实例化的[3]编写Mapper层这里编写sql语句可以配置在xml文件也可以选择注解配置记得链接数据库配置SQL提示(如果用xml可以不管这个)(4)封装数据三种解决方案方案一因为我们是要封装从数据库拿出来的数据所以只需要操作Mapper层即可方案二起别名和实体类属性名一样即可方案三最常用配置文件即可驼峰命名规则映射即数据库字段create_time自动转为createTime(5)前后端联调测试我们基于nginx服务器作为代理(中转)服务器基于nginx服务器的反向代理进行传递解析我们nginx中的配置文件2.删除部门(根据部门id删除)请求参数样例/depts?id1/depts?id2即delete from dept where id#{id}不难看出我们需要接受一个参数这个参数其实就是id那我们Controller是和前端对接自然是要负责接收参数的这边讲解如何接收参数Controlloer接收参数方式一通过HttpServletRequest对象获取请求参数(Http协议中有说明这个对象)DeleteMapping(/depts) public Result delete(HttpServletRequestrequest){ String idStr request.getParameter(id); int id Integer.parseInt(idStr); System.out.println(根据ID删除部门: id); return Result.success(); }方式二通过Spring提供的注解RequestParamDeleteMapping(/depts) public Result delete(RequestParam(id)Integer deptId){ System.out.println(根据ID删除数据deptId); return Result.success(); }注意一旦使用RequestParam这个注解那么参数就必须传递否则报错因为required默认为true,不传递参数会报错如果你想避免这个则只需要把required改为false即可DeleteMapping(/depts) public Result delete(RequestParam(value id,required false) Integer deptId){ System.out.println(根据ID删除数据deptId); return Result.success(); }方法三 请求参数名与形参名相同则可省略RequestParam注解当你知道如何接收参数之后余下的调用方法都是和查询部门一样了3.新增部门即插入数据请求类型为post请求参数样例--不难看出是个json格式{name: 教研部}json参数接收我们看到在controller中需要接收前端传递的请求参数。 那接下来我们就先来看看在服务器端的Controller程序中如何获取json格式的参数。JSON格式的参数通常会使用一个实体对象进行接收 。规则JSON数据的键名与方法形参对象的属性名相同并需要使用RequestBody注解标识。在我们的Service层中可以进行业务逻辑的数据在这里我们要新增两个字段一个是createTime一个是updateTime4.修改部门-查询回显修改数据1.查询回显也就是当你需要修改一个部门的数据的时候需要先点击编辑/修改这一步其实就是获取这个部门的信息所以其实也就是根据id进行查询也就是查询回显如果形参和路径参数名字一样注解可省略写入路径参数名字Controller层GetMapping(/depts/{id})----{id}是路径参数的占位符 public Result findById(PathVariable(id)Integer id){ System.out.println(查询部门数据id);Dept dept deptService.getInfo(id);--这里我们只需返回一个对象就行而非集合return Result.success(dept); }Service层Override public Dept getInfo(Integer id) { return deptMapper.getInfo(id); }Mapper层Select(select id, name, create_time, update_time from dept where id#{id}) Dept getInfo(Integer id);这个请求路径其实是我们RESTful规范中的类型为GET请求为/depts/1(2,3....)三个注解的本质区别注解数据来源URL示例典型场景PathVariableURL路径中/depts/1RESTful风格获取资源IDRequestParamURL?后面/depts?name技术查询参数、分页、筛选Param不是给URL用的不直接对应URLMyBatis的SQL参数命名简单来说PathVariable是获取路径参数的信息在这个GET请求中语义为获取id(主键)的数据的信息但是RequestParam是获取后面的信息它是一种查询参数更多的是用来筛选和分页2.修改数据Controller层PutMapping(/depts) public Result update(RequestBody Dept dept){ System.out.println(修改部门数据dept); deptService.put(dept); return Result.success(); }Service层Override public void put(Dept dept) { System.out.println(修改部门数据);//更新的时候并不需要修改createTimedept.setUpdateTime(LocalDateTime.now()); deptMapper.put(dept); System.out.println(修改部门数据成功); }Mapper层Update(update dept set name#{name},update_time#{updateTime} where id#{id}) void put(Dept dept);另外的我们可以将公共的请求路径提取出来放在类上面日志技术LogbackLogback是非常优秀的日志技术也是我们需要去学习和掌握的Slf4j则类似于一种规范提供了一套标准接口和抽象类也就是让我们的Logback去实现Logback快速入门Spring中有依赖传递的特性所以这个依赖我们就无需引入了logback.xml配置放在src/main/resources目录下即可自建一个logback.xml配置如下?xml version1.0 encodingUTF-8? configuration !-- 控制台输出 -- appender nameSTDOUT classch.qos.logback.core.ConsoleAppender encoder classch.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 levelALL appender-ref refSTDOUT / /root /configuration定义日志记录对象private static final Logger logLoggerFactory.getLogger(LogTest.class);创建日志对象Test public void testLog(){ log.debug(开始计算...); int sum 0; try { int[] nums {1, 5, 3, 2, 1, 4, 5, 4, 6, 7, 4, 34, 2, 23}; for (int i 0; i nums.length; i) { sum nums[i]; } } catch (Exception e) { log.error(程序运行出错, e); } log.info(计算结果为: sum); log.debug(结束计算...); }Logback配置文件logback.xml如果要控制日志输入到文件中!-- 按照每天生成日志文件 -- appender nameFILE classch.qos.logback.core.rolling.RollingFileAppender rollingPolicy classch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy !-- 日志文件输出的文件名, %i表示序号 -- FileNamePatternD:/tlias-%d{yyyy-MM-dd}-%i.log/FileNamePattern !-- 最多保留的历史日志文件数量 -- MaxHistory30/MaxHistory !-- 最大文件大小超过这个大小会触发滚动到新文件默认为 10MB -- maxFileSize10MB/maxFileSize /rollingPolicy encoder classch.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 /appenderlevel后面说明了日志的输出级别即决定了输出哪些日志后面的名称引用即决定了将日志输出到什么地方比如这里就是控制台和文件日志输出内容控制台版本其中%msg即日志信息即你调用debug或info这些方法的时候传递进来的信息文件版本其实和控制台版本差不多只不过是输出在文件里重点是日志存放路径并且可以指定日志文件的名字格式Logback日志级别按照级别从低到高如下项目里最常用开发环境用 debug生产环境用 info如果你的输出等级设置为info那么debug和trace就不会输出如果你的输出等级设置为debug那么trace就不会输出Logback优化项目引入lombok这个依赖之后我们可以在类上方加注解Slf4j这就等于是创建了一个日志对象省略这个代码private static final Logger logLoggerFactory.getLogger(LogTest.class);创建日志对象另外log提供了占位符方便我们使用就不需要字符串拼接了