当前位置: 首页> 教育> 就业 > 肇庆企业做网站_网络服务提供者接到权利人通知后_上海百度首页优化_东莞关键词排名推广

肇庆企业做网站_网络服务提供者接到权利人通知后_上海百度首页优化_东莞关键词排名推广

时间:2025/7/16 14:17:27来源:https://blog.csdn.net/weixin_68453343/article/details/147238267 浏览次数:0次
肇庆企业做网站_网络服务提供者接到权利人通知后_上海百度首页优化_东莞关键词排名推广

目录

一、基本介绍

1.1 开发规范

1.2  Apifox

1.3 工程搭建

二、查询部门 

2.1 基本实现

2.2 数据封装

2.3 前后端联调测试 

三、删除部门 

 3.1 需求

3.2 简单参数接收(获取前端传入的id进行删除)

3.3 代码实现 

3.4 前后端联调测试(接2.3 ) 

四、新增部门

4.1 需求

4.2 json参数接收以及Apifox测试

 4.3 代码实现

4.4 前后端联调测试(接3.4)

五、修改部门 

5.1 查询回显

5.1.1 需求

5.1.2 路径参数接收及Apifox测试

 5.1.3 代码实现

5.2 修改数据 

 5.2.1 需求

5.2.2 代码实现

5.3 @RequestMapping

六、日志技术 

6.1 概述

6.2 日志框架

6.3 Logback快速入门

6.4 Logback配置文件详解

6.5 Logback日志级别

6.6 案例日志记录 


一、基本介绍

1.1 开发规范

目前基本都是采用的前后台分离开发方式,如下图所示:

基于前后台分离开发的模式下,后台开发者开发一个功能的具体流程如下图所示: 

  1. 需求分析:首先我们需要阅读需求文档,分析需求,理解需求。

  2. 接口定义:查询接口文档中关于需求的接口的定义,包括地址,参数,响应数据类型等等

  3. 前后台并行开发:各自按照接口文档进行开发,实现需求

  4. 测试:前后台开发完了,各自按照接口文档进行测试

  5. 前后段联调测试:前段工程请求后端工程,测试功能

传统URL风格如下:

  • http://localhost:8080/user/getById?id=1 GET:查询id为1的用户

  • http://localhost:8080/user/saveUser POST:新增用户

  • http://localhost:8080/user/updateUser POST:修改用户

  • http://localhost:8080/user/deleteUser?id=1 GET:删除id为1的用户

我们看到,原始的传统URL呢,定义比较复杂,而且将资源的访问行为对外暴露出来了。而且,对于开发人员来说,每一个开发人员都有自己的命名习惯,就拿根据id查询用户信息来说的,不同的开发人员定义的路径可能是这样的:getByIdselectByIdqueryByIdloadById... 。 每一个人都有自己的命名习惯,如果都按照各自的习惯来,一个项目组,几十号或上百号人,那最终开发出来的项目,将会变得难以维护,没有一个统一的标准。

基于REST风格URL如下:

  • http://localhost:8080/users/1 GET:查询id为1的用户

  • http://localhost:8080/users POST:新增用户

  • http://localhost:8080/users PUT:修改用户

  • http://localhost:8080/users/1 DELETE:删除id为1的用户

其中总结起来,就一句话:通过URL定位要操作的资源,通过HTTP动词(请求方式)来描述具体的操作。 

在REST风格的URL中,通过四种请求方式,来操作数据的增删改查。

  • GET : 查询

  • POST :新增

  • PUT : 修改

  • DELETE :删除

我们看到如果是基于REST风格,定义URL,URL将会更加简洁、更加规范、更加优雅

注意事项:

  • REST是风格,是约定方式,约定不是规定,可以打破

  • 描述模块的功能通常使用复数,也就是加s的格式来描述,表示此类资源,而非单个资源。如:users、emps、books…

因为在浏览器地中所发起的所有的请求,都是GET方式的请求。那大家就需要思考两个问题:

  • 前后端都在并行开发,后端开发完对应的接口之后,如何对接口进行请求测试呢?

  • 前后端都在并行开发,前端开发过程中,如何获取到数据,测试页面的渲染展示呢?

那这里我们就可以借助一些接口测试工具,比如项:Postman、Apipost、Apifox等。

1.2  Apifox

介绍:Apifox是一款集成了Api文档、Api调试、Api Mock、Api测试的一体化协作平台。

作用:接口文档管理、接口请求测试、Mock服务。

官网: https://apifox.com/

直接下载安装即可(一键安装) 

1.3 工程搭建

1.   创建 SpringBoot 工程,并引入 web 开发起步依赖、 mybatis mysql 驱动、 lombok
2.   创建数据库表 dept ,并在 application.yml 中配置数据库的基本信息。
3.   准备基础代码结构,并引入实体类 Dept 及统一的响应结果封装类 Result

 首先如下图创建一个空项目

得到如下图的空项目 

在右键新建一个模块(如下图) 

 注意!注意!注意!

如果报以下错误:(说明是Lombok包的错误。可以不在这里勾选,直接在pom.xml添加依赖。即使勾选了出现以下错误,直接在pom.xml添加依赖也可以解决)

java: java.lang.NoSuchFieldError: Class com.sun.tools.javac.tree.JCTree$JCImport does not have member field 'com.sun.tools.javac.tree.JCTree qualid'

     <dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.30</version></dependency>

在DataDrip中创建一个数据库,如下图:

代码如下:

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');

创建表如下:

接下来设置数据库连接的配置文件,在resources包下建yml文件(如下图)

yml中的代码如下:

#数据源配置
spring:datasource:driver-class-name: com.mysql.cj.jdbc.Driverurl: jdbc:mysql://localhost:3306/tliasusername: rootpassword: 123456
#mybatis配置
mybatis:configuration:log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

接下来创建以下四个软件包(如下图)

在pojo软件包下创建2个如下图的实体类 

Dept代码如下:

package com.orange.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;
}

Result代码如下:

package com.orange.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;}}

 接下来在新建DeptMapper接口(如下图)

代码如下:

package com.orange.mapper;import org.apache.ibatis.annotations.Mapper;@Mapper//应用程序在运行时,会自动的为该接口创建一个实现类对象(代理对象),并且会自动将该实现类对象存入IOC容器 --bean
public interface DeptMapper {}

 接下来在创建impl包和包下的DeptService类(如下图)

代码如下:

package com.orange.service;public interface DeptService {
}

接下来在创建DeptService接口的实现类(如下图) 

代码如下:

package com.orange.service.impl;import com.orange.service.DeptService;
import org.springframework.stereotype.Service;@Service  //把对象交给IOC容器管理
public class DeptServiceImpl implements DeptService {
}

接下来在建DeptController类(如下图)

 代码如下:

package com.orange.controller;import org.springframework.web.bind.annotation.RestController;@RestController
public class DeptController {
}

至此!结束!可通过以下网盘获取:

通过网盘分享的文件:WebProject001
链接: https://pan.baidu.com/s/1phcOon0YDuM4g1yq8k5v4g?pwd=0706 提取码: 0706 
--来自百度网盘超级会员v4的分享 

二、查询部门 

2.1 基本实现

2.1 完成项目见: 通过网盘分享的文件:WebProject001
链接: https://pan.baidu.com/s/1R3ViT2J4fKMpWHrJyPZNlw?pwd=0706 提取码: 0706 
--来自百度网盘超级会员v4的分享

 

实现如下: 

 

 1). Controller层

DeptController 中,增加 list 方法,代码如下:

package com.orange.controller;import com.orange.pojo.Dept;
import com.orange.pojo.Result;
import com.orange.service.DeptService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;import java.util.List;@RestController
public class DeptController {//调用一个Service@Autowiredprivate DeptService deptService;@RequestMapping(value = "/depts",method = RequestMethod.GET)// 或者使用该注解: @GetMapping("/depts")public Result list(){System.out.println("查询全部部门数据");List<Dept> deptList= deptService.findAll();return Result.success(deptList);}}

2). Service层

DeptService 中,增加 findAll方法,代码如下:

public interface DeptService {/*** 查询所有部门*/public List<Dept> findAll();
}

DeptServiceImpl 中,增加 findAll方法,代码如下:

package com.orange.service.impl;import com.orange.mapper.DeptMapper;
import com.orange.pojo.Dept;
import com.orange.service.DeptService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;import java.util.List;//调用Mapper接口的方法@Service  //把对象交给IOC容器管理
public class DeptServiceImpl implements DeptService {//调用Mapper接口的方法@Autowiredprivate DeptMapper deptMapper;@Overridepublic List<Dept> findAll() {return deptMapper.findAll();}
}

3). Mapper层

DeptMapper 中,增加 findAll方法,代码如下:

package com.orange.mapper;import com.orange.pojo.Dept;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;import java.util.List;@Mapper//应用程序在运行时,会自动的为该接口创建一个实现类对象(代理对象),并且会自动将该实现类对象存入IOC容器 --bean
public interface DeptMapper {@Select("select id,name,create_time,update_time from dept order by update_time desc")List<Dept> findAll();
}

功能逻辑见下图: 

2.2 数据封装

在上述测试中,我们发现部门的数据中,id、name两个属性是有值的,但是createTime、updateTime两个字段值并未成功封装,而数据库中是有对应的字段值的

 

A.    实体类属性名 和 数据库表查询返回的字段名一致, mybatis 会自动封装。
B.    如果 实体类属性名 和 数据库表查询返回的字段名不一致,不能自动封装。

 1). 手动结果映射

在DeptMapper接口方法上,通过 @Results及@Result 进行手动结果映射。

package com.orange.mapper;import com.orange.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//应用程序在运行时,会自动的为该接口创建一个实现类对象(代理对象),并且会自动将该实现类对象存入IOC容器 --bean
public interface DeptMapper {// column:字段名   property:属性名@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();
}

 

2). 起别名

在SQL语句中,对不一样的列名起别名,别名和实体类属性名一样。

@Select("select id, name, create_time createTime, update_time updateTime from dept")
public List<Dept> findAll();

3). 开启驼峰命名(推荐)

如果字段名与属性名符合驼峰命名规则,mybatis会自动通过驼峰命名规则映射。驼峰命名规则: abc_xyz => abcXyz

  • 表中字段名:abc_xyz

  • 类中属性名:abcXyz

在application.yml中做如下配置,开启开关。

mybatis:configuration:map-underscore-to-camel-case: true

2.3 前后端联调测试 

前端测试环境:通过网盘分享的文件:nginx-1.22.0-web.zip
链接: https://pan.baidu.com/s/1xE6b7x4ussomwYlU_B9Wdw?pwd=0706 提取码: 0706 
--来自百度网盘超级会员v4的分享

直接解压到不带中文路径的文件夹中,点击nginx.exe文件进行运行(会一闪而过,但是其实已经开启,也在任务管理器 ->详细信息中可以查看,如下图)

访问测试:http://localhost:90 ,出现以下界面表示成功

1). 浏览器发起请求,请求的是localhost:90 ,那其实请求的是nginx服务器。

2). 在nginx服务器中呢,并没有对请求直接进行处理,而是将请求转发给了后端的tomcat服务器,最终由tomcat服务器来处理该请求。

1). 安全:由于后端的tomcat服务器一般都会搭建集群,会有很多的服务器,把所有的tomcat暴露给前端,让前端直接请求tomcat,对于后端服务器是比较危险的。

2). 灵活:基于nginx的反向代理实现,更加灵活,后端想增加、减少服务器,对于前端来说是无感知的,只需要在nginx中配置即可。

3). 负载均衡:基于nginx的反向代理,可以很方便的实现后端tomcat的负载均衡操作。

具体的请求访问流程如下: 

  1. location:用于定义匹配特定uri请求的规则。

  2. ^~ /api/:表示精确匹配,即只匹配以/api/开头的路径。

  3. rewrite:该指令用于重写匹配到的uri路径。

  4. proxy_pass:该指令用于代理转发,它将匹配到的请求转发给位于后端的指令服务器。

三、删除部门 

完成项目:通过网盘分享的文件:WebProject001
链接: https://pan.baidu.com/s/1r9so_LLmzFKktClqI0Aqtg?pwd=0706 提取码: 0706 
--来自百度网盘超级会员v4的分享

 3.1 需求

删除部门数据。在点击 "删除" 按钮,会根据ID删除部门数据。

 

3.2 简单参数接收(获取前端传入的id进行删除)

 在controller中,需要接收前端传递的请求参数。 那接下来,我们就先来看看在服务器端的Controller程序中,如何获取这类简单参数。 具体的方案有如下三种:

均是在DeptController类中添加方法(如下图)

  • 方案一:通过原始的 HttpServletRequest 对象获取请求参数

/**
* 根据ID删除部门 - 简单参数接收: 方式一 (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 注解,将请求参数绑定给方法形参

@DeleteMapping("/depts")
public Result delete(@RequestParam("id") Integer deptId){System.out.println("根据ID删除部门: " + deptId);return Result.success();
}

@RequestParam 注解的value属性,需要与前端传递的参数名保持一致 。

@RequestParam注解required属性默认为true,代表该参数必须传递,如果不传递将报错。 如果参数可选,可以将属性设置为false。 

  • 方案三:如果请求参数名与形参变量名相同,直接定义方法形参即可接收。(省略@RequestParam)

 @DeleteMapping("/depts")public Result delete(Integer id){System.out.println("根据ID删除部门: " + id);return Result.success();}

3.3 代码实现 

1). Controller层

DeptMapper 中,增加 delete 方法,代码实现如下:

package com.orange.controller;import com.orange.pojo.Dept;
import com.orange.pojo.Result;
import com.orange.service.DeptService;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;import java.util.List;@RestController
public class DeptController {//调用一个Service@Autowiredprivate DeptService deptService;@RequestMapping(value = "/depts",method = RequestMethod.GET)// 或者使用该注解: @GetMapping("/depts")public Result list(){System.out.println("查询全部部门数据");List<Dept> deptList= deptService.findAll();return Result.success(deptList);}/**删除部门** *///参数名与形参变量名相同@DeleteMapping("/depts")public Result delete(Integer id){System.out.println("根据ID删除部门: " + id);deptService.deletById(id);return Result.success();}}

2). Service层

DeptService 中,增加 deleteById 方法,代码实现如下:

package com.orange.service;import com.orange.pojo.Dept;import java.util.List;public interface DeptService {List<Dept> findAll();/** 根据id删除部门* */void deletById(Integer id);
}

DeptServiceImpl 中,增加 deleteById 方法,代码实现如下: 

package com.orange.service.impl;import com.orange.mapper.DeptMapper;
import com.orange.pojo.Dept;
import com.orange.service.DeptService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;import java.util.List;//调用Mapper接口的方法@Service  //把对象交给IOC容器管理
public class DeptServiceImpl implements DeptService {//调用Mapper接口的方法@Autowiredprivate DeptMapper deptMapper;@Overridepublic List<Dept> findAll() {return deptMapper.findAll();}/*** 根据id删除部门* */@Overridepublic void deletById(Integer id) {deptMapper.deletById(id);}}

 3). Mapper层

DeptMapper 中,增加 deleteById 方法,代码实现如下:

package com.orange.mapper;import com.orange.pojo.Dept;
import org.apache.ibatis.annotations.*;import java.util.List;@Mapper//应用程序在运行时,会自动的为该接口创建一个实现类对象(代理对象),并且会自动将该实现类对象存入IOC容器 --bean
public interface DeptMapper {@Select("select id,name,create_time,update_time from dept order by update_time desc")List<Dept> findAll();/** * 根据id删除删除部门* */@Delete("delete from dept where id=#{id}")void deletById(int id);}

对于 DML 语句来说,执行完毕,也是有返回值的,返回值代表的是增删改操作,影响的记录数,所以可以将执行 DML 语句的方法返回值设置为 Integer。 但是一般开发时,是不需要这个返回值的,所以也可以设置为void。 

 在Apifox中输入:http://localhost:8080/depts?id=6  将id为6的进行删除

3.4 前后端联调测试(接2.3 ) 

在浏览其中输入:http://localhost:90,选择部门进行删除测试

四、新增部门

4.1 需求

点击 "新增部门" 的按钮之后,弹出新增部门表单,填写部门名称之后,点击确定之后,保存部门数据。 

4.2 json参数接收以及Apifox测试

在controller中,需要接收前端传递的请求参数。 那接下来,我们就先来看看在服务器端的Controller程序中,如何获取json格式的参数。

  • JSON格式的参数,通常会使用一个实体对象进行接收 。

  • 规则:JSON数据的键名与方法形参对象的属性名相同,并需要使用@RequestBody注解标识。

 前端传递的请求参数格式为json,内容如下:{"name":"研发部"}。这里,我们可以通过一个对象来接收,只需要保证对象中有name属性即可。

 在DeptController中输入以下代码:

 

    /*** 新增部门** 因为是json格式:{"name":"研发部"}* 可以使用Dept对象中的name属性来接收,只要保证:JSON数据的键名与方法形参对象的属性名相同*并需要使用@RequestBody注解标识* */@PostMapping("/depts")public Result add(@RequestBody Dept dept){System.out.println("新增部门:"+dept.getName());return Result.success();}

接下来使用Apifox进行测试,如下图 

 

 IDEA控制台得到如下图输出

 4.3 代码实现

 

1). Controller层

DeptController中增加方法save,具体代码如下:

package com.orange.controller;import com.orange.pojo.Dept;
import com.orange.pojo.Result;
import com.orange.service.DeptService;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;import java.util.List;@RestController
public class DeptController {//调用一个Service@Autowiredprivate DeptService deptService;@RequestMapping(value = "/depts",method = RequestMethod.GET)// 或者使用该注解: @GetMapping("/depts")public Result list(){System.out.println("查询全部部门数据");List<Dept> deptList= deptService.findAll();return Result.success(deptList);}/**删除部门** *///参数名与形参变量名相同@DeleteMapping("/depts")public Result delete(Integer id){System.out.println("根据ID删除部门: " + id);deptService.deletById(id);return Result.success();}/*** 新增部门** 因为是json格式:{"name":"研发部"}* 可以使用Dept对象中的name属性来接收,只要保证:JSON数据的键名与方法形参对象的属性名相同*并需要使用@RequestBody注解标识* */@PostMapping("/depts")public Result add(@RequestBody Dept dept){System.out.println("新增部门:"+dept);deptService.add(dept);return Result.success();}}

2). Service层

DeptService中增加接口方法save,具体代码如下:

package com.orange.service;import com.orange.pojo.Dept;import java.util.List;public interface DeptService {List<Dept> findAll();/** 根据id删除部门* */void deletById(Integer id);/** 新增部门* */void add(Dept dept);
}

DeptServiceImpl中增加save方法,完成添加部门的操作,具体代码如下:

package com.orange.service.impl;import com.orange.mapper.DeptMapper;
import com.orange.pojo.Dept;
import com.orange.service.DeptService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;import java.time.LocalDateTime;
import java.util.List;//调用Mapper接口的方法@Service  //把对象交给IOC容器管理
public class DeptServiceImpl implements DeptService {//调用Mapper接口的方法@Autowiredprivate DeptMapper deptMapper;@Overridepublic List<Dept> findAll() {return deptMapper.findAll();}/*** 根据id删除部门* */@Overridepublic void deletById(Integer id) {deptMapper.deletById(id);}/** 新增部门* */@Overridepublic void add(Dept dept) {//1. 补全基础属性 -creatTime,updateTimedept.setCreateTime(LocalDateTime.now());dept.setUpdateTime(LocalDateTime.now());//2. 调用Mapper接口方法插入数据deptMapper.insert(dept);}}

3). Mapper层

如果在mapper接口中,需要传递多个参数,可以把多个参数封装到一个对象中。 在SQL语句中获取参数的时候,#{...} 里面写的是对象的属性名【注意是属性名,不是表的字段名】。

package com.orange.mapper;import com.orange.pojo.Dept;
import org.apache.ibatis.annotations.*;import java.util.List;@Mapper//应用程序在运行时,会自动的为该接口创建一个实现类对象(代理对象),并且会自动将该实现类对象存入IOC容器 --bean
public interface DeptMapper {@Select("select id,name,create_time,update_time from dept order by update_time desc")List<Dept> findAll();/*** 根据id删除删除部门* */@Delete("delete from dept where id=#{id}")void deletById(int id);/** 新增部门#{对象属性名}**** */@Insert("insert into dept(name,create_time,update_time) values(#{name},#{createTime},#{updateTime}) ")void insert(Dept dept);}

4.4 前后端联调测试(接3.4)

在浏览其中输入:http://localhost:90,选择部门进行添加测试

五、修改部门 

完成项目:通过网盘分享的文件:WebProject001
链接: https://pan.baidu.com/s/1nRGSsFUVu3nhHw406Pp-Lw?pwd=0706 提取码: 0706 
--来自百度网盘超级会员v4的分享

5.1 查询回显

5.1.1 需求

 当我们点击 "编辑" 的时候,需要根据ID查询部门数据,然后用于页面回显展示。

5.1.2 路径参数接收及Apifox测试

/depts/1/depts/2 这种在url中传递的参数,我们称之为路径参数。 那么如何接收这样的路径参数呢 ?

路径参数:通过请求URL直接传递参数,使用{…}来标识该路径参数,需要使用 @PathVariable获取路径参数。如下所示:

如果路径参数名与controller方法形参名称一致,@PathVariable注解的value属性是可以省略的。 

  在DeptController中输入以下代码:

 

代码如下:

 /*** 根据id查询部门** */@GetMapping("/depts/{id}")public Result getInfo(@PathVariable Integer id){System.out.println("根据ID查询部门数据: " + id);return Result.success();}

 接下来使用Apifox进行测试,如下图 

IDEA控制台输出如下:

 5.1.3 代码实现

 

1). Controller层

DeptController 中增加 getById方法,具体代码如下:

package com.orange.controller;import com.orange.pojo.Dept;
import com.orange.pojo.Result;
import com.orange.service.DeptService;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;import java.util.List;@RestController
public class DeptController {//调用一个Service@Autowiredprivate DeptService deptService;@RequestMapping(value = "/depts",method = RequestMethod.GET)// 或者使用该注解: @GetMapping("/depts")public Result list(){System.out.println("查询全部部门数据");List<Dept> deptList= deptService.findAll();return Result.success(deptList);}/**删除部门** *///参数名与形参变量名相同@DeleteMapping("/depts")public Result delete(Integer id){System.out.println("根据ID删除部门: " + id);deptService.deletById(id);return Result.success();}/*** 新增部门** 因为是json格式:{"name":"研发部"}* 可以使用Dept对象中的name属性来接收,只要保证:JSON数据的键名与方法形参对象的属性名相同*并需要使用@RequestBody注解标识* */@PostMapping("/depts")public Result add(@RequestBody Dept dept){System.out.println("新增部门:"+dept);deptService.add(dept);return Result.success();}/*** 根据id查询部门** */@GetMapping("/depts/{id}")public Result getInfo(@PathVariable Integer id){System.out.println("根据ID查询部门数据: " + id);Dept dept = deptService.getById(id);return Result.success(dept);}}

2). Service层

DeptService 中增加 getById方法,具体代码如下:

package com.orange.service;import com.orange.pojo.Dept;import java.util.List;public interface DeptService {List<Dept> findAll();/** 根据id删除部门* */void deletById(Integer id);/** 新增部门* */void add(Dept dept);/*** 根据id查询部门** */Dept getById(Integer id);
}

DeptServiceImpl 中增加 getById方法,具体代码如下:

package com.orange.service.impl;import com.orange.mapper.DeptMapper;
import com.orange.pojo.Dept;
import com.orange.service.DeptService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;import java.time.LocalDateTime;
import java.util.List;//调用Mapper接口的方法@Service  //把对象交给IOC容器管理
public class DeptServiceImpl implements DeptService {//调用Mapper接口的方法@Autowiredprivate DeptMapper deptMapper;@Overridepublic List<Dept> findAll() {return deptMapper.findAll();}/*** 根据id删除部门* */@Overridepublic void deletById(Integer id) {deptMapper.deletById(id);}/** 新增部门* */@Overridepublic void add(Dept dept) {//1. 补全基础属性 -creatTime,updateTimedept.setCreateTime(LocalDateTime.now());dept.setUpdateTime(LocalDateTime.now());//2. 调用Mapper接口方法插入数据deptMapper.insert(dept);}/*** 根据id查询部门** */@Overridepublic Dept getById(Integer id) {return deptMapper.getById(id);}}

3). Mapper层

DeptMapper 中增加 getById 方法,具体代码如下:

package com.orange.mapper;import com.orange.pojo.Dept;
import org.apache.ibatis.annotations.*;import java.util.List;@Mapper//应用程序在运行时,会自动的为该接口创建一个实现类对象(代理对象),并且会自动将该实现类对象存入IOC容器 --bean
public interface DeptMapper {@Select("select id,name,create_time,update_time from dept order by update_time desc")List<Dept> findAll();/*** 根据id删除删除部门* */@Delete("delete from dept where id=#{id}")void deletById(int id);/** 新增部门#{对象属性名}**** */@Insert("insert into dept(name,create_time,update_time) values(#{name},#{createTime},#{updateTime}) ")void insert(Dept dept);/*** 根据id查询部门** */@Select("select id,name,create_time,update_time from dept where  id = #{id}")Dept getById(Integer id);}

5.2 修改数据 

 5.2.1 需求

查询回显回来之后,就可以对部门的信息进行修改了,修改完毕之后,点击确定,此时,就需要根据ID修改部门的数据。

5.2.2 代码实现

1). Controller层

DeptController 中增加 update 方法,具体代码如下:

package com.orange.controller;import com.orange.pojo.Dept;
import com.orange.pojo.Result;
import com.orange.service.DeptService;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;import java.util.List;@RestController
public class DeptController {//调用一个Service@Autowiredprivate DeptService deptService;@RequestMapping(value = "/depts",method = RequestMethod.GET)// 或者使用该注解: @GetMapping("/depts")public Result list(){System.out.println("查询全部部门数据");List<Dept> deptList= deptService.findAll();return Result.success(deptList);}/**删除部门** *///参数名与形参变量名相同@DeleteMapping("/depts")public Result delete(Integer id){System.out.println("根据ID删除部门: " + id);deptService.deletById(id);return Result.success();}/*** 新增部门** 因为是json格式:{"name":"研发部"}* 可以使用Dept对象中的name属性来接收,只要保证:JSON数据的键名与方法形参对象的属性名相同*并需要使用@RequestBody注解标识* */@PostMapping("/depts")public Result add(@RequestBody Dept dept){System.out.println("新增部门:"+dept);deptService.add(dept);return Result.success();}/*** 根据id查询部门** */@GetMapping("/depts/{id}")public Result getInfo(@PathVariable Integer id){System.out.println("根据ID查询部门数据: " + id);Dept dept = deptService.getById(id);return Result.success(dept);}/*** 修改部门** */@PutMapping("/depts")public Result update(@RequestBody Dept dept){System.out.println("修改部门:"+dept);deptService.update(dept);return Result.success();}}

2). Service层

DeptService 中增加 update 方法。

package com.orange.service;import com.orange.pojo.Dept;import java.util.List;public interface DeptService {List<Dept> findAll();/** 根据id删除部门* */void deletById(Integer id);/** 新增部门* */void add(Dept dept);/*** 根据id查询部门** */Dept getById(Integer id);/*** 修改部门** */void update(Dept dept);
}

DeptServiceImpl 中增加 update 方法。 由于是修改操作,每一次修改数据,都需要更新updateTime。所以,具体代码如下:

package com.orange.service.impl;import com.orange.mapper.DeptMapper;
import com.orange.pojo.Dept;
import com.orange.service.DeptService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;import java.time.LocalDateTime;
import java.util.List;//调用Mapper接口的方法@Service  //把对象交给IOC容器管理
public class DeptServiceImpl implements DeptService {//调用Mapper接口的方法@Autowiredprivate DeptMapper deptMapper;@Overridepublic List<Dept> findAll() {return deptMapper.findAll();}/*** 根据id删除部门* */@Overridepublic void deletById(Integer id) {deptMapper.deletById(id);}/** 新增部门* */@Overridepublic void add(Dept dept) {//1. 补全基础属性 -creatTime,updateTimedept.setCreateTime(LocalDateTime.now());dept.setUpdateTime(LocalDateTime.now());//2. 调用Mapper接口方法插入数据deptMapper.insert(dept);}/*** 根据id查询部门** */@Overridepublic Dept getById(Integer id) {return deptMapper.getById(id);}/*** 修改部门** */@Overridepublic void update(Dept dept) {//1. 补全基础属性 - updateTimedept.setUpdateTime(LocalDateTime.now());//2. 调用Mapper接口方法更新部门deptMapper.update(dept);}}

3). Mapper层

DeptMapper 中增加 update 方法,具体代码如下:

package com.orange.mapper;import com.orange.pojo.Dept;
import org.apache.ibatis.annotations.*;import java.util.List;@Mapper//应用程序在运行时,会自动的为该接口创建一个实现类对象(代理对象),并且会自动将该实现类对象存入IOC容器 --bean
public interface DeptMapper {@Select("select id,name,create_time,update_time from dept order by update_time desc")List<Dept> findAll();/*** 根据id删除删除部门* */@Delete("delete from dept where id=#{id}")void deletById(int id);/** 新增部门#{对象属性名}**** */@Insert("insert into dept(name,create_time,update_time) values(#{name},#{createTime},#{updateTime}) ")void insert(Dept dept);/*** 根据id查询部门** */@Select("select id,name,create_time,update_time from dept where  id = #{id}")Dept getById(Integer id);/*** 修改部门** */@Update("update dept set name =#{name},update_time = #{updateTime} where id= #{id}")void update(Dept dept);}

 Apifox测试如下:

5.3 @RequestMapping

到此呢,关于基本的部门的增删改查功能,我们已经实现了。 我们会发现,我们在 DeptController 中所定义的方法,所有的请求路径,都是 /depts 开头的,只要操作的是部门数据,请求路径都是 /depts 开头。

那么这个时候,我们其实是可以把这个公共的路径 /depts 抽取到类上的,那在各个方法上,就可以省略了这个 /depts 路径。 代码如下:

一个完整的请求路径,应该是类上的 @RequestMapping 的value属性 + 方法上的 @RequestMapping的value属性。 

六、日志技术 

6.1 概述

  • 什么是日志?

    • 日志就好比生活中的日记,可以随时随地记录你生活中的点点滴滴。

    • 程序中的日志,是用来记录应用程序的运行信息、状态信息、错误信息的。

  • 为什么要在程序中记录日志呢?

    • 便于追踪应用程序中的数据信息、程序的执行过程。

    • 便于对应用程序的性能进行优化。

    • 便于应用程序出现问题之后,排查问题,解决问题。

    • 便于监控系统的运行状态。

    • ... ...

  • 之前我们编写程序时,也可以通过 System.out.println(...) 来输出日志,为什么我们还要学习单独的日志技术呢?

这是因为,如果通过 System.out.println(...) 来记录日志,会存在以下几点问题:

  • 硬编码。所有的记录日志的代码,都是硬编码,没有办法做到灵活控制,要想不输出这个日志了,只能删除掉记录日志的代码。

  • 只能输出日志到控制台。

  • 不便于程序的扩展、维护。

所以,在现在的项目开发中,我们一般都会使用专业的日志框架,来解决这些问题。

6.2 日志框架

  • JUL:这是JavaSE平台提供的官方日志框架,也被称为JUL。配置相对简单,但不够灵活,性能较差。

  • Log4j:一个流行的日志框架,提供了灵活的配置选项,支持多种输出目标。

  • Logback:基于Log4j升级而来,提供了更多的功能和配置选项,性能由于Log4j。

  • Slf4j(Simple Logging Facade for Java)简单日志门面,提供了一套日志操作的标准接口及抽象类,允许应用程序使用不同的底层日志框架。

6.3 Logback快速入门

1). 准备工作:引入logback的依赖(springboot中无需引入,在springboot中已经传递了此依赖)

<dependency><groupId>ch.qos.logback</groupId><artifactId>logback-classic</artifactId><version>1.4.11</version>
</dependency>

2). 引入配置文件 logback.xml

 

代码如下:

<?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>

3). 记录日志:定义日志记录对象Logger,记录日志 

 

代码如下:

package com.orange;import org.junit.jupiter.api.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;import java.time.LocalDateTime;public class LogTest {//定义日志记录对象private static final Logger log = LoggerFactory.getLogger(LogTest.class);@Testpublic void testLog(){log.debug("开始计算...");int sum = 0;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];}log.info("计算结果为: "+sum);log.debug("结束计算...");}}

6.4 Logback配置文件详解

Logback日志框架的配置文件叫 logback.xml

完整logback.xml代码如下:

<?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表示序号 --><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><!-- 日志输出级别 --><root level="ALL"><appender-ref ref="STDOUT" /><appender-ref ref="FILE" /></root>
</configuration>

该配置文件是对Logback日志框架输出的日志进行控制的,可以来配置输出的格式、位置及日志开关等。

常用的两种输出日志的位置:控制台、系统文件。

1). 如果需要输出日志到控制台。添加如下配置:

<!-- 控制台输出 -->
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"><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>

2). 如果需要输出日志到文件。添加如下配置:

<!-- 按照每天生成日志文件 -->
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender"><rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy"><!-- 日志文件输出的文件名, %i表示序号 --><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>

3). 日志开关配置 (开启日志(ALL),取消日志(OFF))

<!-- 日志输出级别 -->
<root level="ALL"><!--输出到控制台--><appender-ref ref="STDOUT" /><!--输出到文件--><appender-ref ref="FILE" />
</root>

6.5 Logback日志级别

日志级别指的是日志信息的类型,日志都会分级别,常见的日志级别如下(优先级由低到高):

日志级别说明记录方式
trace追踪,记录程序运行轨迹 【使用很少】log.trace("...")
debug调试,记录程序调试过程中的信息,实际应用中一般将其视为最低级别 【使用较多】log.debug("...")
info记录一般信息,描述程序运行的关键事件,如:网络连接、io操作 【使用较多】log.info("...")
warn警告信息,记录潜在有害的情况 【使用较多】log.warn("...")
error错误信息 【使用较多】log.error("...")

可以在配置文件logback.xml中,灵活的控制输出那些类型的日志。(大于等于配置的日志级别的日志才会输出)

<!-- 日志输出级别 -->
<root level="info"><!--输出到控制台--><appender-ref ref="STDOUT" /><!--输出到文件--><appender-ref ref="FILE" />
</root>

6.6 案例日志记录 

package com.orange.controller;import com.orange.pojo.Dept;
import com.orange.pojo.Result;
import com.orange.service.DeptService;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;import java.util.List;@Slf4j
@RestController
public class DeptController {//调用一个Service@Autowiredprivate DeptService deptService;@RequestMapping(value = "/depts",method = RequestMethod.GET)// 或者使用该注解: @GetMapping("/depts")public Result list(){//System.out.println("查询部门列表");log.info("查询部门列表");List<Dept> deptList= deptService.findAll();return Result.success(deptList);}/**删除部门** *///参数名与形参变量名相同@DeleteMapping("/depts")public Result delete(Integer id){//System.out.println("根据id删除部门, id=" + id);log.info("根据id删除部门, id: {}" , id);deptService.deletById(id);return Result.success();}/*** 新增部门** 因为是json格式:{"name":"研发部"}* 可以使用Dept对象中的name属性来接收,只要保证:JSON数据的键名与方法形参对象的属性名相同*并需要使用@RequestBody注解标识* */@PostMapping("/depts")public Result add(@RequestBody Dept dept){//System.out.println("新增部门, dept=" + dept);log.info("新增部门, dept: {}" , dept);deptService.add(dept);return Result.success();}/*** 根据id查询部门** */@GetMapping("/depts/{id}")public Result getInfo(@PathVariable Integer id){//System.out.println("根据ID查询, id=" + id);log.info("根据ID查询, id: {}" , id);Dept dept = deptService.getById(id);return Result.success(dept);}/*** 修改部门** */@PutMapping("/depts")public Result update(@RequestBody Dept dept){//System.out.println("修改部门, dept=" + dept);log.info("修改部门, dept: {}" , dept);deptService.update(dept);return Result.success();}}

lombok中提供的@Slf4j注解,可以简化定义日志记录器这步操作。添加了该注解,就相当于在类中定义了日志记录器,就下面这句代码:

private static Logger log = LoggerFactory. getLogger(Xxx. class);

关键字:肇庆企业做网站_网络服务提供者接到权利人通知后_上海百度首页优化_东莞关键词排名推广

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

责任编辑: