软件测试学习笔记丨后端架构优化设计 - spring boot 增删改查操作
作者:测试人
- 2024-05-06 北京
本文字数:7177 字
阅读完需:约 24 分钟
本文转自测试人社区,原文链接:https://ceshiren.com/t/topic/30757
一,springBoot 项目 导入依赖
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency>
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.junit.jupiter</groupId> <artifactId>junit-jupiter-api</artifactId> <version>5.8.2</version> <scope>test</scope> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>RELEASE</version> <scope>compile</scope> </dependency> <dependency> <groupId>com.fasterxml.jackson.dataformat</groupId> <artifactId>jackson-dataformat-xml</artifactId> <version>2.13.1</version> </dependency> <!-- mysql连接 --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.29</version> </dependency> <!--mybatis坐标--> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.5.9</version> </dependency> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>2.1.0</version> </dependency> <!-- https://mvnrepository.com/artifact/tk.mybatis/mapper-spring-boot-starter --> <dependency> <groupId>tk.mybatis</groupId> <artifactId>mapper-spring-boot-starter</artifactId> <version>2.1.5</version> </dependency> <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-boot-starter</artifactId> <version>3.0.0</version> </dependency> <dependency> <groupId>org.mapstruct</groupId> <artifactId>mapstruct</artifactId> <version>1.4.2.Final</version> </dependency> </dependencies>
<build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> <plugin> <groupId>org.mybatis.generator</groupId> <artifactId>mybatis-generator-maven-plugin</artifactId> <version>1.3.7</version> <!--插件设置--> <configuration> <!--允许移动生成的文件--> <verbose>true</verbose> <!--启用覆盖--> <overwrite>true</overwrite> <!--自动生成配置 如果名字是generatorConfig.xml可以省略配置--> <configurationFile>src/main/resources/generator/generatorConfig.xml</configurationFile> </configuration> <dependencies> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.29</version> <scope>runtime</scope> </dependency> <dependency> <groupId>tk.mybatis</groupId> <artifactId>mapper</artifactId> <version>4.1.5</version> </dependency> </dependencies> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.8.1</version> <configuration> <source>12</source> <target>12</target> <annotationProcessorPaths> <path> <groupId>org.mapstruct</groupId> <artifactId>mapstruct-processor</artifactId> <version>1.4.2.Final</version> </path> </annotationProcessorPaths> </configuration> </plugin> </plugins> </build>
<!-- <profiles>--><!-- <profile>--><!-- <id>dev</id>--><!-- <properties>--><!-- <profilesActive>dev</profilesActive>--><!-- </properties>--><!-- </profile>--><!-- <profile>--><!-- <id>test</id>--><!-- <properties>--><!-- <profilesActive>test</profilesActive>--><!-- </properties>--><!-- <activation>--><!-- <!– 设置为默认环境的配置–>--><!-- <activeByDefault>true</activeByDefault>--><!-- </activation>--><!-- </profile>--><!-- </profiles>-->
</project>复制代码
二, 配置数据源(application.yml 文件为例)
#spring数据库连接配置spring: datasource: driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://10.52.46.11:33066/advert username: mysql password: 123456 #Swagger页面展示内容配置 mvc: pathmatch: matching-strategy: ANT_PATH_MATCHER复制代码
三,添加 mapper 扫描路径(加上 MapperScan 注解)
package com.oppo.advertSpring;
import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;import tk.mybatis.spring.annotation.MapperScan;
@SpringBootApplication@MapperScan("com.oppo.advertSpring.mapper")public class AdvertSpringApplication { public static void main(String[] args) { SpringApplication.run(AdvertSpringApplication.class, args); }
}复制代码
四,配置 mybatis 相关依赖(application.yml 文件为例)
#mybatis连接配置mybatis: configuration: use-actual-param-name: true mapper-locations: classpath:mapper/*.xml type-aliases-package: com.oppo.advertSpring.entity复制代码
五,Bean 拷贝实现
5.1 Bean 拷贝实现的背景及解决方法
背景:
前端通过接口直接操作数据库表的实体类对象,对应的字段都暴露出来,数据库字段数据泄密风险
解决方法:
(1)使用自定义的 dto 进行业务逻辑编写 entity:entity 是实体类,会在数据库中存在的实际的表,包括它的每一个字段 DTO: 与 Controller 交互的对象,都当做是 DTO 对象,dto 存储前端传参字段,不透露数据表
(2)使用 bean 拷贝 dto 的实体类与 entity 的实体类进行转换 bean 拷贝:DTO 与 entity 转换
5.2 实现工具类 mapstruct
注解处理器
可以生成 JavaBean 之间那的映射代码
类型安全, 高性能, 无依赖性
通过注解的方式帮我们实现 JavaBean 之间的转换
5.3 mapstruct 依赖导入
<dependencies> <dependency> <groupId>org.mapstruct</groupId> <artifactId>mapstruct</artifactId> <version>1.4.2.Final</version> </dependency> </dependencies>
<build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.8.1</version> <configuration> <source>12</source> <target>12</target> <annotationProcessorPaths> <path> <groupId>org.mapstruct</groupId> <artifactId>mapstruct-processor</artifactId> <version>1.4.2.Final</version> </path> </annotationProcessorPaths> </configuration> </plugin> </plugins> </build>复制代码
六,编写业务代码
6.1 定义一个 dto 的实体类,实体类字段根据需要取必要的传参字段,字段少于 entity 的实体类
package com.oppo.advertSpring.dto;
import io.swagger.annotations.ApiModel;import io.swagger.annotations.ApiModelProperty;import javax.persistence.Column;import javax.persistence.Table;
@ApiModel(value = "精准词表", description = "advert.ads_search_kwctrl")@Table(name = "ads_search_kwctrl")public class AdsSearchKwctrlDto {
/** * 应用ID */ @Column(name = "app_id") private Integer appId;
/** * 关键词 */ private String keyword;
/** * 来源[1运营添加 2广告主添加] */ @ApiModelProperty(value = "来源", allowableValues = "1,2") private Integer source;
public Integer getAppId() { return appId; }
public void setAppId(Integer appId) { this.appId = appId; }
public String getKeyword() { return keyword; }
public void setKeyword(String keyword) { this.keyword = keyword; }
public Integer getSource() { return source; }
public void setSource(Integer source) { this.source = source; }
@Override public String toString() { return "AdsSearchKwctrlDto{" + "appId=" + appId + ", keyword='" + keyword + ''' + ", source=" + source + '}'; }}复制代码
6.2 定义一个 KwctrlService 接口,传参为 dto 的实体类
package com.oppo.advertSpring.service;
import com.oppo.advertSpring.dto.AdsSearchKwctrlDto;import com.oppo.advertSpring.util.Result;
import java.text.ParseException;
public interface KwctrlService {
Result insertKwctl(AdsSearchKwctrlDto adsSearchKwctrlDto) throws ParseException;
Result updateKwctl(AdsSearchKwctrlDto adsSearchKwctrlDto) throws ParseException;
Result findKwctl(AdsSearchKwctrlDto adsSearchKwctrlDto);
Result deleteKwctl(AdsSearchKwctrlDto adsSearchKwctrlDto);
}复制代码
6.3 创建转换类,实现 AdsSearchKwctrl 转换成 AdsSearchKwctrlDto
使用 mapper 注解,导入的包为 mapstruct 的包
@Mapper(componentModel = “spring”) 生成的映射器是一个单例范围的 Spring bean,可以通过以下方式检索 @Autowired
package com.oppo.advertSpring.converter;
import com.oppo.advertSpring.dto.AdsSearchKwctrlDto;import com.oppo.advertSpring.entity.AdsSearchKwctrl;import org.mapstruct.Mapper;import org.mapstruct.Mapping;import org.mapstruct.Mappings;
@Mapper(componentModel = "spring")public interface AdsSearchKwctrConverter { // AdsSearchKwctrl转换成AdsSearchKwctrlDto的实现
@Mappings({ @Mapping(target = "appId", source = "appId"), @Mapping(target = "keyword", source = "keyword"), @Mapping(target = "source", source = "source") }) AdsSearchKwctrl dtoForKwctl(AdsSearchKwctrlDto adsSearchKwctrlDto);
}复制代码
6.4 创建接口实现类 KwctrlServiceImpl
package com.oppo.advertSpring.service;
import com.oppo.advertSpring.converter.AdsSearchKwctrConverter;import com.oppo.advertSpring.dto.AdsSearchKwctrlDto;import com.oppo.advertSpring.entity.AdsSearchKwctrl;import com.oppo.advertSpring.mapper.AdsSearchKwctrlMapper;import com.oppo.advertSpring.util.Result;import com.oppo.advertSpring.util.TimestampUtil;import lombok.SneakyThrows;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Service;import tk.mybatis.mapper.entity.Example;import java.text.ParseException;import java.util.List;
@Servicepublic class KwctrlServiceImpl implements KwctrlService {
@Autowired AdsSearchKwctrlMapper adsSearchKwctrlMapper;
@Autowired AdsSearchKwctrConverter adsSearchKwctrConverter;
TimestampUtil time = new TimestampUtil();
// @SneakyThrows @Override public Result insertKwctl(AdsSearchKwctrlDto adsSearchKwctrlDto) throws ParseException { AdsSearchKwctrl adsSearchKwctrl = adsSearchKwctrConverter.dtoForKwctl(adsSearchKwctrlDto);
adsSearchKwctrl.setInsertTime(time.timestamp()); adsSearchKwctrl.setLastModifyTime(time.timestamp()); int insertNum = adsSearchKwctrlMapper.insert(adsSearchKwctrl); System.out.println(insertNum); return Result.OK().data(adsSearchKwctrl).message("数据插入成功"); }
@Override public Result findKwctl(AdsSearchKwctrlDto adsSearchKwctrlDto) { AdsSearchKwctrl adsSearchKwctrl = adsSearchKwctrConverter.dtoForKwctl(adsSearchKwctrlDto); List<AdsSearchKwctrl> select = adsSearchKwctrlMapper.select(adsSearchKwctrl);// AdsSearchKwctrl one = adsSearchKwctrlMapper.selectOne(adsSearchKwctrl); System.out.println(select); return Result.OK().data(select).message("查找成功"); }
// @SneakyThrows @Override public Result updateKwctl(AdsSearchKwctrlDto adsSearchKwctrlDto) throws ParseException { AdsSearchKwctrl adsSearchKwctrl = adsSearchKwctrConverter.dtoForKwctl(adsSearchKwctrlDto); //查找条件,相当于select * from ads_search_kwctrl where app_id= and keyword= Example example = new Example(AdsSearchKwctrl.class); Example.Criteria criteria = example.createCriteria(); criteria.andEqualTo("appId", adsSearchKwctrl.getAppId());
List<AdsSearchKwctrl> kwctrlList = adsSearchKwctrlMapper.selectByExample(example); System.out.println("查找结果的第一条数据:" + kwctrlList.get(0)); //获取appId对应的唯一主键 Integer id = kwctrlList.get(0).getKwctrlId(); adsSearchKwctrl.setKwctrlId(id); //填充最新修改时间 adsSearchKwctrl.setLastModifyTime(time.timestamp()); //根据查找结果更新这条数据 int updateNum = adsSearchKwctrlMapper.updateByPrimaryKeySelective(adsSearchKwctrl); System.out.println( "更新数据:"+ updateNum + "条"); //查询修改后的数据 AdsSearchKwctrl selectOne = adsSearchKwctrlMapper.selectOne(adsSearchKwctrl); System.out.println("更新后的数据:"+selectOne); return Result.OK().data(selectOne).message("修改成功"); }
@Override public Result deleteKwctl(AdsSearchKwctrlDto adsSearchKwctrlDto) { AdsSearchKwctrl adsSearchKwctrl = adsSearchKwctrConverter.dtoForKwctl(adsSearchKwctrlDto); int delete = adsSearchKwctrlMapper.delete(adsSearchKwctrl); System.out.println(delete); return Result.OK().data(adsSearchKwctrl).message("删除成功"); }
}复制代码
6.5 controller 创建对应的接口
package com.oppo.advertSpring.controller;
import com.oppo.advertSpring.dto.AdsSearchKwctrlDto;import com.oppo.advertSpring.entity.AdsSearchKwctrl;import com.oppo.advertSpring.service.KwctrlService;import com.oppo.advertSpring.util.Result;import io.swagger.annotations.ApiOperation;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.web.bind.annotation.PostMapping;import org.springframework.web.bind.annotation.RequestBody;import org.springframework.web.bind.annotation.RestController;import java.text.ParseException;
@RestControllerpublic class KwctrlController {
@Autowired KwctrlService kwctrlService;
@ApiOperation("精准词insert接口") @PostMapping(path = "/insertKwctl", produces = "application/json") Result insertKwctl(@RequestBody AdsSearchKwctrlDto adsSearchKwctrlDto) throws ParseException { return kwctrlService.insertKwctl(adsSearchKwctrlDto); }
@ApiOperation("精准词find接口") @PostMapping(path = "/findKwctl", produces = "application/json") Result findKwctl(@RequestBody AdsSearchKwctrlDto adsSearchKwctrlDto){ return kwctrlService.findKwctl(adsSearchKwctrlDto); }
@ApiOperation("精准词update接口") @PostMapping(path = "/updateKwctl", produces = "application/json") Result updateKwctl(@RequestBody AdsSearchKwctrlDto adsSearchKwctrlDto) throws ParseException { return kwctrlService.updateKwctl(adsSearchKwctrlDto); }
@ApiOperation("精准词delete接口") @PostMapping(path = "/deleteKwctl", produces = "application/json") Result deleteKwctl(@RequestBody AdsSearchKwctrlDto adsSearchKwctrlDto){ return kwctrlService.deleteKwctl(adsSearchKwctrlDto); }
}复制代码
6.6 Swagger 页面调用接口看是否正常
软件测试开发免费视频教程分享
划线
评论
复制
发布于: 刚刚阅读数: 3
版权声明: 本文为 InfoQ 作者【测试人】的原创文章。
原文链接:【http://xie.infoq.cn/article/bb533793cc6978b8531c63e3f】。文章转载请联系作者。
测试人
关注
专注于软件测试开发 2022-08-29 加入
霍格沃兹测试开发学社,测试人社区:https://ceshiren.com/t/topic/22284







评论