你好,我是Qiuner. 为记录自己编程学习过程和帮助别人少走弯路而写博客
这是我的 github https://github.com/Qiuner ⭐️
gitee https://gitee.com/Qiuner 🌹
如果本篇文章帮到了你 不妨点个赞吧~ 我会很高兴的 😄 (^ ~ ^)
想看更多 那就点个关注吧 我会尽力带来有趣的内容 😎
博客介绍
- 本项目也是很早之前写过的项目 当时没有打算上传,写的很杂,整篇文档的精髓是 请求参数处理办法、类开发五部走、接口开发(控制器开发四步走)即使您没有接触过后端开发 在看了几集视频后来看这几个会对您构建后端认识有着巨大帮助
- 请善用文章的目录功能
请求参数类型及处理办法
Headers http://localhost/api/setmeal Path: /admin/setmeal
参数名称 | 参数值 | 是否必须 | 示例 | 备注 |
Content-Type | application/json | 是 |
三、@RequestBody
从http请求body部分获取参数,通常用于接受json或xml格式
路径参数 http://localhost/api/setmeal/44 Path: /admin/setmeal/{id}
参数名称 | 示例 | 备注 |
status | 1 | 套餐状态,1表示起售,0表示停售 |
一、@PathVariable:
用于从请求的URL路径中获取路径变量的值。路径变量是URL中的一部分,用于在RESTful风格的API中传递数据。路径变量的值会直接嵌入到URL路径中,并使用占位符 {}
来表示,Spring MVC 会根据占位符中的变量名将值注入到方法参数中。
@GetMapping("/users/{userId}") public String getUser(@PathVariable("userId") Long userId) { // 根据用户ID查询用户信息 }
查询参数 http://localhost/api/setmeal/page?page=1&pageSize=10&status= Path: /admin/setmeal/page
Query:
参数名称 | 是否必须 | 示例 | 备注 |
categoryId | 否 | 分类id | |
name | 否 | 套餐名称 | |
page | 是 | 页码 | |
pageSize | 是 | 每页记录数 | |
status | 否 | 套餐起售状态 |
//以下代码是请求参数对应接收类 @Data public class SetmealPageQueryDTO implements Serializable { private int page; private int pageSize; private String name; //分类id private Integer categoryId; //状态 0表示禁用 1表示启用 private Integer status; }
- 为什么这里可以不加任何东西就获取到参数呢?
- 当Spring MVC发现一个方法的参数类型不是基本类型(如int、String等)而是一个POJO(Plain Old Java Object)时,它会尝试从请求中提取参数,并将参数的值赋给该POJO对象对应的属性
二、@RequestParam:
用于从请求的查询参数中获取单个参数值。通常用于GET请求或者POST请求中的查询参数。在GET请求中,查询参数会附加在URL后面,如 ?key1=value1&key2=value2
,而在POST请求中,查询参数会放在请求体中,需要使用 @RequestParam
指定参数名来获取值。
@GetMapping("/search") public String search(@RequestParam("keyword") String keyword) { // 处理查询操作 }
还可以使用@ModelAttribute
类开发五步走
一:添加Spring Framework中的类标识注解 @RestController 这个注解后面可以跟上命名,当同一个项目中有两个一样的类名时,就可以使用这个注解来进行区别
二:添加处理路径 @RequestMapping(“/”)
三:添加日志记录器 原生是logging。这里我选择使用@Slf4j 创建日志记录器,并进行管理。使用该注解后,使用 log 对象进行管理
四:生成接口文档 @Api(tags = "标题")
这里使用Swagger生成接口文档,方便测试
五:对象管理 使用 @Autowired 来进行依赖注入
接口开发
接口开发主要有三个地方需要开发,一是controller二是 service 三是mapper
控制器controller开发四步走
@PostMapping("/admin/employee") @ApiOperation("新增员工") public Result save(@RequestBody EmployeeDTO employeeDTO){ //RequestBody 注解的作用是告诉Spring MVC框架,要将HTTP请求的body部分(通常是JSON或XML格式的数据)映射到方法参数 employeeDTO 上。 log.info("新增员工:{}",employeeDTO); employeeService.sava(employeeDTO); }
一: 确认控制器地址 @PostMapping(“/admin/employee”) 确认后面的请求路劲该写什么
二:编写传输的数据模型 编写一个实体用来接收前端传递过来的数据模型 EmployeeDTO employeeDTO
三:编写处理返回结果的类 Result
四:调用业务逻辑层的相关方法 employeeService.sava(employeeDTO);
附加: log.info(“新增员工:{}”,employeeDTO);便于调试@ApiOperation(“新增员工”)使得生成出来的接口测试站点更加容易阅读
业务逻辑层开发
一:编写接口的方法
二: 在实现类中实现
三:封装好属性与数据
记得在业务逻辑类前加上@service标签
业务逻辑层(service)开发小技巧
遇到前端传来数据与数据库实体差距过大创建了两个对象的时候,业务逻辑层使用对象拷贝能更快拿到数据
项目名词解释
- **序列化:**把对象转化为可传输的字节序列过程称为序列化。
**反序列化:**把字节序列还原为对象的过程称为反序列化。 - 设置工厂连接对象,这里的工厂指的是设计模式
问题
- 什么是消息转换器
- 什么是@builder构建器
- 切面是什么,有什么用解决了什么问题
- 什么加了builder注解后会让方法变成私有
开发的一些常见东西
- 购物车中的物品结算时,前端已经做了为空不能结算的校验,但后端还是要再做一遍,因为可能会出现不从前端发来的请求
项目的约定
- 管理端发来的请求使用admin为前缀
- 用户端发来的请求使用user为前缀
- 前端提交过来的属性与实体类(根据数据库属性设计的对象)属性差别比较大时,使用dto来封装前端提交过来的数据
- 账号密码默认为123456
开发小技巧
- 更多技巧见:https://blog.csdn.net/lisu061714112/article/details/117856048?ops_request_misc=&request_id=&biz_id=102&utm_term=idea%E4%BB%A3%E7%A0%81%E5%BC%80%E5%8F%91%E6%8A%80%E5%B7%A7&utm_medium=distribute.pc_search_result.none-task-blog-2allsobaiduweb~default-1-117856048.142v99pc_search_result_base3&spm=1018.2226.3001.4187
- 使用alt加回车可以快捷生成未实现的方法
- 多学习别人的工具类是怎么写的
- 多个参数时,实体要放在第一个位置
- 复杂的sql,现在数据库中写一遍试试
- 遇到需要更新某数据时候,可以直接找到数据然后覆盖
项目技术点
- 自定义异常类
- 自定义注解
- 接口文档生成
- 接口开发
- 文件上传
- PageHelper的分页查询
- 让springboot框架来解析接口的数据
- 项目规范:常量类、公共字段注入、数据加密
- BeanUtils用来拷贝对象
- 测试类中代码每次启动都会运行一次
- 依赖注入的深入学习
- Builder模式创建对象
重要零碎 - 面对一个请求中的数据要同时插入两张表的时,在业务逻辑层进行处理,分别插入两张表的数据
- DTO后缀的实体一般用于数据流转,VO后缀用于数据展示,而没有后缀的一般用于与数据库交互
- @Options在mapper层使用该注解可以使得立刻获得插入数据的某项属性,如id
后端开发
开发流程与工具选择
- 使用yapi来管理所有的接口,导入接口文档
- 使用swagger对接口进行测试
- 项目中的这个用来排除不上传的文件
- 拿到项目后可以在maven生命周期中对项目进行编译
反向代理
配置方式
- 此处将前端发来请求中有/api/变成了admin
IDEA 开发小技巧 TODO
- 可在使用TODO来标识
使用MD5对数据 库中密码进行加密
Swagger
- 都是配置形的代码,固定的
- 这样配置能扫描的包包括controller.admin
常用的注解
/* 该注解用于生成接口文档时显示作用于类 */ @Api(tags = "员工相关接口") public class EmployeeController { @PostMapping("/login") @ApiOperation(value = "员工登录方法") // 注意这里 public Result<EmployeeLoginVO> login(@RequestBody EmployeeLoginDTO employeeLoginDTO) { @PostMapping("/logout") @ApiOperation(value = "员工登出方法") public Result<String> logout() { return Result.success(); } }
- 写在控制器下面即可
- 这个规范的叫法是 专注数据传输的类。
静态资源与Controller
- 静态资源只要存在于一个项目中就可被浏览器请求到,不需要后端处理。而控制器则是用于处理动态请求并生成动态内容的组件
- 静态资源就是项目中一个html5文件之类的
- 下面这个就是controller
JWT
动态sql所使用的标签
因为要用到标签所以在xml中进行编写
要注意到几个问题:
一:扫描范围
处理分页查询放回的日期是数组类型数据
- 方法一只能对标注的注解
- 方法二可以全局
- 此处分页查询用来springboot中的page框架自动拼接
想要处理传递过来可变参数可写成以下模式
@PostMapping("/status/{status}")
请求路径
@PutMapping @ApiOperation("编辑员工信息") public Result update(@RequestBody EmployeeDTO employeeDTO){ log.info("编辑员工:{}", employeeDTO); employeeService.update(employeeDTO); return Result.success(); @PostMapping @ApiOperation("新增员工") public Result save(@RequestBody EmployeeDTO employeeDTO){ log.info("新增员工:{}",employeeDTO); employeeService.sava(employeeDTO); /* 一个工具类,这个代表放回成功 */ return Result.success(); }
这是同一个类中的两个方法,都没有指定请求的路径,于是被视为都挂在在类默认路径上,一个是put一个是post请求
公共字段自动填充问题
- 通过定义字段和切面来实现
配置类的写法
- 这样会使得代码会提示
Configuration配置注解
与@Component的区别: @Configuration
是 @Component
注解的特化,它们都是用来声明一个类作为Spring管理的组件,但 @Configuration
有特殊的语义,用于定义Bean和配置项。
启动加载: 配置类通常在Spring应用程序启动时被加载,Spring容器会扫描并解析其中的配置信息,以构建应用程序的应用上下文。
使用事务的办法
xml文件复制的方法
- cv复制后修改这里
让MVC框架来解析接口的数据
- 想要让mvc框架来解析这个接口,将逗号分隔的每个元素封装到list集合中去
加上@RequestParam 注解即可
Redis
一个基于内存的key-value结构数据库。读写性能高,适合存储热点数据(经常访问的),mysql的补充
- 打开服务的时候记得两个窗口都不要关闭
数据类型
在java中操作redis
像营业状态这种只有一个字符的东西就适合存在redis中
一个项目相同类名通过编译办法
一个项目Swagger设置不同页的接口文档办法
- grouName记得设置,不能在创建bean的时候会出错
HttpClient
@Test public void testPOST() throws Exception { /* 1、创建httpclient对象 */ CloseableHttpClient httpClient = HttpClients.createDefault(); /* 2、创建请求对象 */ //Post方式请求 HttpPost httpPost = new HttpPost("http://localhost:8080/admin/employee/login"); //构造json数据 JSONObject jsonObject = new JSONObject(); jsonObject.put("username","admin"); jsonObject.put("password", "123456"); //构造请求体 StringEntity stringEntity = new StringEntity(jsonObject.toString()); //设置请求编码 stringEntity.setContentEncoding("utf-8"); //设置数据类型 stringEntity.setContentType("application/json"); //设置当前Post请求的请求体 httpPost.setEntity(stringEntity); /* 3、发送请求 */ //发送请求 CloseableHttpResponse response = httpClient.execute(httpPost); /* 4、解析返回结果 */ //http响应码 int statusCode = response.getStatusLine().getStatusCode(); //http响应体 HttpEntity entity = response.getEntity(); //将响应体转为String字符串 String body = EntityUtils.toString(entity); System.out.println(body); /* 5、关闭资源 */ //关闭资源 response.close(); httpClient.close(); }
苍穹外卖开发心得(下):https://developer.aliyun.com/article/1548483