软件测试学习笔记丨后端架构优化设计 - 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;
@Service
public 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;
@RestController
public 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
评论