整合第三方技术
整合JUnit
@SpringBootTest
- 类型:测试类注解
- 位置测试类定义上方
- 作用:设置Junit加载的SpringBoot启动类
@SpringBootTest
class SpringbootJunitApplicationTests {}
- classes:设置SpringBoot启动类
- 如果测试类不在引导类所在的包或者子包中需要通过classes属性指定引导类
@SpringBootTest(classes = SpringbootJunitApplicationTests.class)
class SpringbootJunitApplicationTests {}
整合MyBatis
- 核心配置:数据库链接相关信息
- 映射配置:SQL映射(XML/注解)
- 设置Application.yml链接SQL
spring:
datasource:
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://localhost:3306/数据库名
username: SQL账号
password: SQL密码
- 选择依赖项:
- Mybatis Framework
- MySQL Driver
- 编写字段表,如:
// 需要导入Lombok依赖
@Data
public class User{
private Integer id;
private String type;
private String name;
}
- 定义数据层接口与映射配置
@Mapper
public interface UserMapper {
@Select("select * from 表名")
Book getAll();
}
- 测试类中注入dao接口,测试功能
@SpringBootTest
class SpringbootMybatisApplicationTests {
@Autowired
private UserMapper userMapper;
@Test
void contextLoads() {
System.out.println(UserMapper.getAll());
}
}
MySQL配置问题
MySQL 8.x驱动强制要求设置时区
- 修改rul,添加sererTimezone设定
url: jdbc:mysql://localhost:3306/ssm_db?sererTimezone = utf
- 修改MySQL数据库配置
- 驱动类过时,提醒更换为:com.mysql.cj.jdbc.Driver
整合MyBatis-Plus
- MyBatis-plus与MyBatis区别
- 导入坐标不同
- 数据层实现简化
- 手动添加SpringBoot整合MyBatis-Plus坐标,可以通过mvnrepository获取
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.2</version>
</dependency>
- 定义数据层接口与映射配置,继承BaseMapper
@Mapper
public interface BookMapper extends BaseMapper<Book> {
}
整合Druid
- 需要导入Druid对应的starter
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.2.8</version>
</dependency>
- 根据Druid提供的配置方式进行配置(不加默认使用Hikari)
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/ssm_db
username: root
password: root
type: com.alibaba.druid.pool.DruidDataSource
或者
spring:
datasource:
druid:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/ssm_db
username: root
password: root
- 整合第三方技术通用方式
- 导入对应的starter
- 根据提供的配置格式,配置非默认值对应的配置项
基于SpringBoot的SSMP整合案例
- 实体类开发——使用Lombok快速制作实体类
- Dao开发——整合MyBatisPlus,制作数据层测试
- Service开发——基于MyBatisPlus进行增量开发,制作业务层测试类
- Controller开发——基于Restful开发,使用PostMan测试接口功能
- Controller开发——前后端开发协议制作
- 页面开发——基于VUE+ElementUI制作,前后端联调,页面数据处理,页面消息处理
- 列表
- 新增
- 修改
- 删除
- 分页
- 查询
- 项目异常处理
- 按条件查询————页面功能调整、Controller修正功能、Service修正功能
数据层开发
- 配置数据源与MyBatisPlus对应的基础配置
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/ssm_db
username: root
password: root
type: com.alibaba.druid.pool.DruidDataSource
mybatis-plus:
global-config:
db-config:
table-prefix: tbl_
id-type: auto
- 继承BaseMapper并指定泛型
@Mapper
public interface BookMapper extends BaseMapper<Book> {}
- 制作测试类测试结果
@SpringBootTest
class Springboot07SsmpApplicationTests {
@Autowired
private BookMapper bookMapper;
@Test
void contextLoads() {
System.out.println(bookMapper.selectById(1));
}
@Test
void testSave(){
Book book = new Book();
book.setName("张三");
book.setType("张三");
book.setDescription("张三");
bookMapper.insert(book);
}
@Test
void testUpdate(){
Book book = new Book();
book.setId("输入需要更改的id");
book.setName("张三123");
book.setType("张三123");
book.setDescription("张三123");
bookMapper.updateById(book);
}
@Test
void testDelete(){
bookMapper.deleteById(58007553);
}
@Test
void testGetAll(){
System.out.println(bookMapper.selectList(null));
}
……
}
开启MP运行日志
- 方便调试可以开启MyBatisPlus日志
mybatis-plus:
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
数据层开发——分页功能
- 分页操作需要设定分页对象Page
@Test
void testGetPage(){
Page<Book> page = new Page<>(1, 5);
System.out.println(bookMapper.selectPage(page,null));
}
- 分页操作是在MyBatisPlus的上操作的,内部是动拼写SQL语句,因此需要增强对应的功能,使用MyBatisPlus拦截器实现
@Configuration
public class MPConfig {
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor(){
MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();
mybatisPlusInterceptor.addInnerInterceptor(new PaginationInnerInterceptor());
return mybatisPlusInterceptor;
}
}
数据层开发——查询功能
- 使用QueryWrapper对象封装查询条件,推荐使用LambdaQueryWrapper对象
@Test
void testGetBy(){
QueryWrapper<Book> qw = new QueryWrapper<>();
qw.like("name","spring");
bookMapper.selectList(qw);
}
@Test
void testGetBy2(){
LambdaQueryWrapper<Book> qw = new LambdaQueryWrapper<>();
String name = null;
qw.like(name != null,Book::getName,name);
bookMapper.selectList(qw);
}
业务层开发
业务层标准开发——CRUD构建
- 接口定义
public interface BookService {
Book getById(Integer id);
List<Book> getAll();
IPage<Book> getPage(int currentPage,int pageSize);
}
- 实现类定义
@Service
public class BookServiceImpl implements BookService {
@Autowired
private BookMapper bookMapper;
@Override
public Book getById(Integer id) {
return bookMapper.selectById(id);
}
@Override
public List<Book> getAll() {
return bookMapper.selectList(null);
}
@Override
public IPage<Book> getPage(int currentPage, int pageSize) {
IPage<Book> bookIPage = new Page<Book>(currentPage, pageSize);
bookMapper.selectPage(bookIPage,null);
return bookIPage;
}
}
- 测试类定义
@SpringBootTest
public class BookServiceTestCase {
@Autowired
private BookService bookService;
@Test
void testGetById(){
System.out.println(bookService.getById(1));
}
@Test
void testGetAll(){
System.out.println(bookService.getAll());
}
@Test
void testGetPage(){
IPage<Book> page = bookService.getPage(1, 5);
System.out.println(page);
System.out.println(page.getRecords());
}
}
业务层快速开发——MyBatisPlus构建
- 快速开发方案
- 使用MyBatisPlus提供有业务层通用接口
(IService<T>)
与业务层通用实现类(ServiceImpl<M,T>)
- 在通用类基础上做功能重载或功能追加
- 注意重载时不要覆盖原始操作,避免原始提供的功能丢失
- 接口定义
public interface BookIService extends IService<Book> {
// 追加的操作与原始操作通过命名区分
}
- 实现类定义
@Service
public class BookIServiceImpl extends ServiceImpl<BookMapper, Book> implements BookIService {
// 在BookIService类追加的操作,在此类追加功能
}
表现层开发
- 基于Restful进行表现层接口开发
- 使用Postman测试表现层接口功能
@RestController
@RequestMapping("/books")
public class BookController {
@Autowired
private BookIService bookIService;
@GetMapping
public List<Book> getAll(){
return bookIService.list();
}
……
}
- 基于Restful制作表现层接口
- 新增:POST
- 删除:DELETE
- 修改:PUT
- 查询:GET
- 接收参数
- 实体数据:@RequestBody
- 路径变量:@pathVariable
表现层信息——一致性处理
- 设计表现层返回结果的模型类,用于后端与前端进行数据格式统一
@Data
public class R {
private Boolean flag;
private Object data;
public R(){}
public R(Boolean flag){
this.flag = flag;
}
public R(Boolean flag,Object data){
this.flag = flag;
this.data = data;
}
}
- 表现层接口统一返回值类型结果
@RestController
@RequestMapping("/books")
public class BookController {
@Autowired
private BookIService bookIService;
@PostMapping
public R save(@RequestBody Book book){
return new R(bookIService.save(book));
}
@GetMapping
public R getAll(){
return new R(true,bookIService.list());
}
}
- 业务操作成功或失败返回数据格式
{
"flag": true/false,
"data": null
}
- 后台代码BUG导致数据格式不统一性
{
"timestamp": "2023-01-11T04:39:12.424+00:00",
"status": 500,
"error": "Internal Server Error",
"path": "/books"
}
前后端协议联调(略)
- 前后端分离结构设计中页面归属前端服务器
- 单体工程页面放置在resources目录下的static目录中(建议执行clean)
弹出添加窗口
handleCreate() {
// 重置表单
this.resetForm();
this.dialogFormVisible = true;
},
清除数据
// 重置表单
resetForm() {
this.formData = {};
},
添加
//添加
handleAdd () {
// 发送异步请求
axios.post("/books",this.formData).then((res) =>{
//如果操作成功,关闭弹层,显示数据
if (res.data.flag){
// 1.关闭弹层
this.dialogFormVisible = false;
this.$message.success("添加成功");
}else {
this.$message.error("添加失败");
}
}).finally(()=>{
// 2.重新加载数据
this.getAll();
});
},
取消添加
//取消
cancel(){
this.dialogFormVisible = false;
this.$message.info("操作取消");
},
删除
// 删除
handleDelete(row) {
console.log(row);
this.$confirm("此操作永久删除当前信息,是否继续?","提示",{type: "info"}).then(()=>{
axios.delete("/books/"+row.id).then((res)=>{
if (res.data.flag){
this.$message.success("删除成功");
}else {
this.$message.error("删除失败");
}
}).finally(()=>{
this.getAll();
})
}).catch(()=>{
this.$message.info("取消操作");
})
},
弹出编辑窗口
//弹出编辑窗口
handleUpdate(row) {
// 发送异步请求
axios.get("/books/"+row.id).then((res)=>{
if (res.data.flag && res.data.data != null){
this.dialogFormVisible4Edit = true;
this.formData = res.data.data;
}else {
this.$message.error("数据同步失败,自动刷新");
}
}).finally(()=>{
this.getAll();
});
},
修改
- 修改
//修改
handleEdit() {
axios.put("/books",this.formData).then((res) =>{
if (res.data.flag){
// 1.关闭弹层
this.dialogFormVisible4Edit = false;
this.$message.success("修改成功");
}else {
this.$message.error("修改失败");
}
}).finally(()=>{
// 2.重新加载数据
this.getAll();
});
},
- 取消添加
//取消
cancel(){
this.dialogFormVisible = false;
//添加修改弹窗
this.dialogFormVisible4Edit = false;
this.$message.info("操作取消");
},