CRUD流程
第一步:DAO层(与数据库进行交互)
1.阅读开发文档,按照开发文档在ideal里创建结构
2.创建实体类,和对应的mapper层(可以用mybits),mapper层主要与数据库进行交互。![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/b05d7421a09d4948b87d45f7849d1683.png#pic_center)
3.DAO层【DO(实体类),mapper文件(接口类)----------->xml文件(接口文件具体的实现方法)】![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/fd84d296115c451e80f1d9c40ecf76cc.png#pic_center)
4.mapper文件(定义接口和方法名称)接口一般是增删改查四种,例如:
package com.xcyy.system.mapper;
import com.xcyy.common.objdect.entity.MeractivitiesDO;
/**
* @author ksm
* @description 针对表【MerActivities(商户活动的表,存储活动相关信息)】/**
* 根据ID查询
*/
MeractivitiesDO selectById(String ActivityID);
* @createDate 2024-06-21 11:38:21
* @Entity com.xcyy.system.domain.Meractivities
*/
public interface MeractivitiesMapper {
/**
* 根据ID查询
*/
MeractivitiesDO selectById(String ActivityID);
/**
* 查询所有
*/
MeractivitiesDO selectAll();
/**
* 新增信息
*/
int insertMertable(MeractivitiesDO meractivities);
/**
* 删除信息
*/
int deleteByActivityid(String ActivityID);
/**
* 更新信息
*/
int updateByActivityid(MeractivitiesDO meractivities);
}
5.xml文件(实现具体的mapper方法)例如:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.xcyy.system.mapper.MeractivitiesMapper">
<resultMap id="BaseResultMap" type="com.xcyy.common.objdect.entity.MeractivitiesDO">
<id property="activityId" column="activity_id"/>
<result property="imagePath" column="image_url"/>
<result property="link" column="=link"/>
<result property="description" column="description"/>
<result property="creator" column="creator"/>
<result property="createTime" column="create_time"/>
<result property="updateTime" column="update_time"/>
<result property="status" column="status"/>
<result property="title" column="title"/>
<result property="startTime" column="start_time"/>
<result property="endTime" column="end_time" />
</resultMap>
<select id="selectById" parameterType="com.xcyy.common.objdect.entity.MeractivitiesDO" resultMap="BaseResultMap">
select activity_id,image_url,link,
description,creator,create_time,
update_time,status,title,
start_time,end_time from mall_activity
<where>
activity_id = #{activityID}
</where>
</select>
<select id="selectAll" parameterType="com.xcyy.common.objdect.entity.MeractivitiesDO" resultMap="BaseResultMap">
select*
</select>
<insert id="insertMertable" parameterType="com.xcyy.common.objdect.entity.MeractivitiesDO">
INSERT INTO mall_activity
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="activityId != null">activity_id</if>
<if test="imagePath != null">image_url</if>
<if test="link != null">link</if>
<if test="description != null">description</if>
<if test="creator != null">creator</if>
<if test="createTime != null">create_time</if>
<if test="updateTime != null">update_time</if>
<if test="status != null">status</if>
<if test="title != null">title</if>
<if test="startTime != null">start_time</if>
<if test="endTime != null">end_time</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="activityId != null">#{activityId},</if>
<if test="imagePath != null">#{imagePath},</if>
<if test="link != null">#{link},</if>
<if test="description != null">#{description},</if>
<if test="creator != null">#{creator},</if>
<if test="createTime != null">#{createTime},</if>
<if test="updateTime != null">#{updateTime},</if>
<if test="status != null">#{status},</if>
<if test="title != null">#{title},</if>
<if test="startTime != null">#{startTime},</if>
<if test="endTime != null">#{endTime},</if>
</trim>
</insert>
<delete id="deleteByActivityid" parameterType="com.xcyy.common.objdect.entity.MeractivitiesDO">
delete from mall_activity
<where>
activity_id = #{activityID}
</where>
</delete>
<update id="updateByActivityid" parameterType="com.xcyy.common.objdect.entity.MeractivitiesDO">
UPDATE mall_activity
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="activityId != null">activity_id = #{activityId},</if>
<if test="imagePath != null">image_url = #{imagePath},</if>
<if test="link != null">link = #{link},</if>
<if test="description != null">description = #{description},</if>
<if test="creator != null">creator = #{creator},</if>
<if test="createTime != null">create_time = #{createTime},</if>
<if test="updateTime != null">update_time = #{updateTime},</if>
<if test="status != null">status = #{status},</if>
<if test="title != null">title = #{title},</if>
<if test="startTime != null">start_time = #{startTime},</if>
<if test="endTime != null">end_time = #{endTime},</if>
</trim>
where activity_id = #{activityID}
</update>
</mapper>
第二步:Service层(中间层,与DAO层和Controller层进行交互)
1.Service接口层(做一些比基础“增删改查”更复杂的逻辑,比如“排序某个数据库字段(点赞率)并查询第一个字段返回给前端”)例如:
package com.xcyy.system.service;
import com.xcyy.common.objdect.bo.GenericPageRspBO;
import com.xcyy.common.objdect.bo.MeractivitiesBO;
import org.springframework.web.multipart.MultipartFile;
/**
* @author ksm
* @description 针对表【MerActivities(商户活动的表,存储活动相关信息)】的数据库操作Service
* @createDate 2024-06-21 11:38:21
*/
public interface IMeractivitiesService {
MeractivitiesBO selectMeractivitiesById(String activityid);
GenericPageRspBO<MeractivitiesBO> selectAllMeractivities(MeractivitiesBO meractivitiesBO);
int insertMeractivities(MultipartFile multipartFile, MeractivitiesBO meractivitiesBO);
int deleteMeractivitiesById(String activityid);
int updateMeractivitiesById(MultipartFile multipartFile,MeractivitiesBO meractivitiesBO);
}
2.Service实现层(实现接口层的业务)主要是调用Mapper层的CRUD来实现 例如:
package com.xcyy.system.service.impl;
import com.xcyy.common.core.exception.ServiceException;
import com.xcyy.common.core.utils.BeanCopyUtils;
import com.xcyy.common.core.utils.DateTimeUtils;
import com.xcyy.common.core.utils.PageInfo;
import com.xcyy.common.core.utils.PageUtil;
import com.xcyy.common.core.utils.uuid.IdUtils;
import com.xcyy.common.objdect.bo.GenericPageRspBO;
import com.xcyy.common.objdect.bo.MeractivitiesBO;
import com.xcyy.common.objdect.entity.MeractivitiesDO;
import com.xcyy.common.security.utils.SecurityUtils;
import com.xcyy.file.utils.MinIOFileUtils;
import com.xcyy.system.mapper.MeractivitiesMapper;
import com.xcyy.system.service.IMeractivitiesService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;
/**
* @author ksm
* @description 针对表【MerActivities(商户活动的表,存储活动相关信息)】的数据库操作Service实现
* @createDate 2024-06-21 11:38:21
*/
@Service
public class MeractivitiesServiceImpl implements IMeractivitiesService {
@Autowired
MeractivitiesMapper meractivitiesMapper;
// 事务回滚
@Transactional(rollbackFor = ServiceException.class)
@Override
//根据ID查询
public MeractivitiesBO selectMeractivitiesById(String activityid) {
return BeanCopyUtils.deepCopyBean(meractivitiesMapper.selectById(activityid), MeractivitiesBO.class);
}
@Override
//list查询
public GenericPageRspBO<MeractivitiesBO> selectAllMeractivities(MeractivitiesBO meractivitiesBO){
MeractivitiesDO meractivitiesDO = BeanCopyUtils.deepCopyBean(meractivitiesBO, MeractivitiesDO.class);
PageInfo<MeractivitiesDO> meractivitiesDOPageInfo = PageUtil.pageQueryWithCount(
meractivitiesBO.getPageNum(),
meractivitiesBO.getPageSize(),
() -> meractivitiesMapper.selectAll(meractivitiesDO)
);
GenericPageRspBO genericPageRspBO = new GenericPageRspBO();
genericPageRspBO.setTotal(meractivitiesDOPageInfo.getTotal());
genericPageRspBO.setResultList(BeanCopyUtils.deepCopyBeanList(meractivitiesDOPageInfo.getList(), MeractivitiesDO.class));
return genericPageRspBO;
}
// 事务回滚
@Transactional(rollbackFor = ServiceException.class)
@Override
//增,向数据库里增加一行数据,并把图片存入文件数据库
public int insertMeractivities(MultipartFile multipartFile, MeractivitiesBO meractivitiesBO) {
// 上传文件返回文件地址
String fileUrl = MinIOFileUtils.uploadMinIOFile(
multipartFile,
meractivitiesBO.getActivityid().toString(),
"meractivities"
);
//修改文件地址存入数据库
meractivitiesBO.setImagepath(fileUrl);
meractivitiesBO.setActivityid(IdUtils.fastSimpleUUID());
meractivitiesBO.setStatus(Boolean.TRUE);
meractivitiesBO.setCreatetime(DateTimeUtils.getCurrentLocalDate());
meractivitiesBO.setCreator(SecurityUtils.getLoginUser().getUsername());
// 将BO对象转换为DO对象
MeractivitiesDO meractivitiesDO = BeanCopyUtils.deepCopyBean(meractivitiesBO, MeractivitiesDO.class);
return meractivitiesMapper.insertMertable(meractivitiesDO);
}
// 事务回滚
@Transactional(rollbackFor = ServiceException.class)
@Override
//删除数据库的一行数据
public int deleteMeractivitiesById(String activityid) {
// 删除文件
MinIOFileUtils.deleteMinIOFile(
new String[]{
meractivitiesMapper.selectById(activityid).getImagePath()
}
);
// 删除数据库
return meractivitiesMapper.deleteByActivityid(activityid);
}
// 事务回滚
@Transactional(rollbackFor = ServiceException.class)
@Override
public int updateMeractivitiesById(MultipartFile multipartFile, MeractivitiesBO meractivitiesBO) {
meractivitiesBO.setUpdatetime(DateTimeUtils.getCurrentLocalDate());
if (!multipartFile.isEmpty()) {
// 上传文件返回文件地址
String fileUrl = MinIOFileUtils.uploadMinIOFile(
multipartFile,
meractivitiesBO.getActivityid().toString(),
"meractivities");
//修改文件地址存入实体层
meractivitiesBO.setImagepath(fileUrl);
}
// 将BO对象转换为DO对象
MeractivitiesDO meractivitiesDO = BeanCopyUtils.deepCopyBean(meractivitiesBO, MeractivitiesDO.class);
return meractivitiesMapper.updateByActivityid(meractivitiesDO);
}
}
第三步:Controller层
1.用来实现和前端的交互
1.http的get、post、put、delete 的原理
http与服务器交互提供了四种方式,get、post、put和delete
get:是相当于select查询操作,不会改变或影响服务器端的任何内容信息;
post:是相当于insert插入操作,会增加数据,存入到服务器端;
put:是相当于update更新操作,不会增加数据,只是修改服务器端的信息;
delete:是相当于delete删除操作,是用来删除资源的;
url:是资源定位符
get、put、delete对应的url可以理解为:/url/XXX,post对应的url可以理解为:/url
get对应的就是getMapping
put对应的就是putMapping
post对应的就是postMapping
delete对应的就是deleteMapping
一般传输少量数据直接用getMapping就可以了,getMapping的请求url的形式有两种,
一种是 后台访问地址?参数1= “参数1”&参数2=“参数2”,在后台取出路径上的值可以用,在后台程序对应方法的路径可以只需要写路径即可
第二种是 后台访问地址 ?参数,在后台程序对应方法的路径之后需要加一个{参数名}类似于:
@RequiresPermissions("system:meractivities:query")
@GetMapping("/find/{id}")
public MeractivitiesDTO selectMeractivitiesById(@PathVariable String id) {
return BeanCopyUtils.deepCopyBean(meractivitiesService.selectMeractivitiesById(id), MeractivitiesDTO.class);
}
在后台取出路径上的参数时,
第一种用@RequestParam,这个注解的value指定路径上的参数名,require用来标识是否是必须要传的参数
@PostMapping("/insert")
public AjaxResult insertMeractivities(@RequestParam("multipartFile")MultipartFile multipartFile, MeractivitiesVO meractivitiesVO) {
return toAjax(meractivitiesService.insertMeractivities(
multipartFile,
BeanCopyUtils.deepCopyBean(meractivitiesVO, MeractivitiesBO.class)
)
);
}
第二种用@PathVariable,这个直接在注解的参数中写入参数名就可以了
@DeleteMapping("/delete/{id}")
public AjaxResult deleteMeractivitiesById(@PathVariable String id) {
return toAjax(meractivitiesService.deleteMeractivitiesById(id));
}
但是用路径url的总长度是有限制的,对参数个数是没有限制的,不同浏览器对url的限长是不一样的,所以需要传输的数据量大的时候或者用表单的时候是需要用到post,postMapping请求的,因为post的请求体是不限制的。
post的参数呢是一个对象,从前端角度出发可以看成一个json格式的字符串,在后台接收的时候,可以直接用一个对象来接收,这个对象前面加上注解@ResquestBody即可
put跟post类似,对应的是更新操作,传过来的也是一个json字符串可以用@RequestBody的形式接收,也可以像get那样,用参数的形式进行传值
delete的用法就跟get类似了,delete对应的是删除,把字段的值传过来即可
2.controller语法
1.@Restcontroller,@RestMapping@Autowired
@RestController//
@RequestMapping(SystemRequestConstants.MALL_ACTIVITY)//这个url地址使用了字典常量,实际上是/XcYy/System/meractivities
public class MeractivitiesController extends BaseController {
@Autowired
private IMeractivitiesService meractivitiesService;//带了这个注解可以免去Test1Entity testEntity = new Test1Entity();这样的语法
@RequiresPermissions("system:meractivities:query")//权限控制
@GetMapping("/find/{id}")//实际上是/XcYy/System/meractivities/find/{id}
public MeractivitiesDTO selectMeractivitiesById(@PathVariable String id) {
return BeanCopyUtils.deepCopyBean(meractivitiesService.selectMeractivitiesById(id), MeractivitiesDTO.class);
}
2.@GetMapping
/**
* 根据ID查询
* @param id
* @return
*/
GetMapping("/select/{id}")
MyStudent selectById(@PathVariable String id)//在控制器中的处理方法的形参中使用@PathVariable注解去获取@RequestMapping中 { } 中传进来的值,并绑定到处理方法定一的形参上。
{
return myStudentMapper.selectByPrimaryKey(id);
}
3.@PostMapping
/**
* 插入数据
* @param id
* @param name
* @param birth
* @param sex
* @return
*/
@PostMapping("/student")
public int insertStu(@RequestParam String id, @RequestParam String name, @RequestParam String birth, @RequestParam String sex)
//@RequestParam用于将指定的请求参数赋值给方法中的形参。
{
MyStudent myStudent = new MyStudent();
myStudent.setsId(id);
myStudent.setsName(name);
myStudent.setsBirth(birth);
myStudent.setsSex(sex);
return myStudentMapper.insert(myStudent);
}
4.@PutMapping
/**
* 局部更新用PatchMapping 全局更新用PutMapping
* @param myStudent
* @return
*/
@PatchMapping("/update")
public int updateById(MyStudent myStudent) {
return myStudentMapper.updateByPrimaryKey(myStudent);
}
5.@DeleteMapping
/**
* 根据ID删除一条数据
*
* @param id
* @return
*/
@DeleteMapping("/delete/{id}")
public int deleteById(@PathVariable String id) {
return myStudentMapper.deleteByPrimaryKey(id);
}
6.对于前端传值的时候注意:
对于json类型的数据(‘Content-Type’: ‘application/json’ ),需要使用@RequestBody接受,否则控制台会报错
对于其他类型的数据(‘Content-Type’: ‘application/x-www-form-urlencoded’),后台可以直接接受
最好使用json传值,因为null值在json中会被正常处理
第四步:使用Postman软件去测试接口
1.软件简介:
如何使用Postman?
下图是Postman的工作区间,各个模块功能的介绍如下:
1、New,在这里创建新的请求、集合或环境;还可以创建更高级的文档、Mock Server 和 Monitor以及API。
2、Import,这用于导入集合或环境。有一些选项,例如从文件,文件夹导入,链接或粘贴原始文本。
3、Runner,可以通过Collection Runner执行自动化测试。后续介绍。
4、Open New,打开一个新的标签,Postman窗口或Runner窗口。
5、My Workspace - 可以单独或以团队的形式创建新的工作区。
6、Invite - 通过邀请团队成员在工作空间上进行协同工作。
7、History - 所有请求的历史记录,这样可以很容易地跟踪你所做的操作。
8、Collections - 通过创建集合来组织你的测试套件。每个集合可能有子文件夹和多个请求。请求或文件夹也可以被复制。
9、Request tab - 这将显示您正在处理的请求的标题。默认对于没有标题的请求会显示“Untitled Request”。
10、HTTP Request - 单击它将显示不同请求的下拉列表,例如 GET, POST, COPY, DELETE, etc. 在测试中,最常用的请求是GET和POST。
11、Request URL - 也称为端点,显示API的URL。.
12、Save - 如果对请求进行了更改,必须单击save,这样新更改才不会丢失或覆盖。
13、Params - 在这里将编写请求所需的参数,比如Key - Value。
14、Authorization - 为了访问api,需要适当的授权。它可以是Username、Password、Token等形式。
15、Headers - 请求头信息
16、Body - 请求体信息,一般在POST中才会使用到
17、Pre-request Script - 请求之前 先执行脚本,使用设置环境的预请求脚本来确保在正确的环境中运行测试。
18、Tests - 这些脚本是在请求期间执行的。进行测试非常重要,因为它设置检查点来验证响应状态是否正常、检索的数据是否符合预期以及其他测试。
19、Settings - 最新版本的有设置,一般用不到。
2.如何处理GET请求:
在Postman的工作区中:
1、选择HTTP请求方式为GET
2、在URL区域输入 链接
3、点击 “Send”按钮
4、你将看到下方返回200状态码
5、在正文中应该有10个用户结果,表明您的测试已经成功运行。
注意: 在某些情况下,Get请求失败可能由于URL无效或需要身份验证。
3.如何处理POST请求:
Step 1)
1、选择HTTP请求方式为POST
2、在URL区域输入 链接:https://jsonplaceholder.typicode.com/users
3、切换到Body选项
Step 2)
Body选项
1、选中raw选项
2、选择JSON
Step 3)
在Body里添加Json代码
**注意:** 检查Body里用到的JSON格式很重要,以确保数据正确。
检测的工具比如:https://jsonformatter.curiousconcept.com/
Step 4)
发送请求
1、完成上述的信息输入,点击Send按钮
2、Status:应该是201,显示为创建成功
3、在Body里返回数据W
s-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3piajE4MzE0NDY5Mzk1,size_1,color_FFFFFF,t_70)
**注意:** 检查Body里用到的JSON格式很重要,以确保数据正确。
检测的工具比如:https://jsonformatter.curiousconcept.com/
Step 4)
发送请求
1、完成上述的信息输入,点击Send按钮
2、Status:应该是201,显示为创建成功
3、在Body里返回数据