学习目标
1.SpringBoot整合MP的分页方法(Ipage)
2.SpringBoot完成数据校验
3.MP实现逆向工程
今日所学
更新项目目录
主要是新增分页中一些字段,然后封装成类
在控制层实现分页查询方法
在dto中添加不可为空以及正则表达式进行判断的注解
1.整合MP实现分页查询
1.1需求分析
// 前端传递的参数:
// page: 表示当前查询的页(默认1)
// size: 每页记录数(默认10)
// 后端返回给前端的数据格式:
{
code:200,
msg:"succes",
data:{
计算得到应有的页数: 总记录数/每页记录数 +1
total: 11,
records: [
{id:"",name:""},
{id:"",name:""},
{id:"",name:""},
...
]
}
}
1.2基于MP实现分页的核心方法
/**
* 分页的测试方法
*/
@Test
public void testPage(){
// API尽量用service, 不用mapper
// E: IPage接口,通过Page类实现了分页的参数传递,和结果的查询
// 分页操作的注意事项: 需要配置类(从官网获取)
// 构造查询条件
long current = 2; // 要查询的当前页页码
long size = 5; // 每页的记录数
IPage<User> page = new Page<>(current,size);
// 通过调用service的page方法获取到返回的IPage对象
IPage<User> result = userService.page(page);
// 获取总记录数
long total = result.getTotal();
System.out.println("total:"+total);
// 获取当前页的记录
List<User> records = result.getRecords();
records.forEach(System.out::println);
}
1.3设计带有分页功能的接口
@Data
public class PageDto implements Serializable {
private Long current;
private Long size;
}
@Data
public class PageResults<T> implements Serializable {
private Long total;
private T records;
}
@PostMapping("/page")
public R page(@RequestBody PageDto dto){
IPage<User> page = new Page<>(dto.getCurrent(),dto.getSize());
IPage<User> result = userService.page(page);
long total = result.getTotal();
List<User> records = result.getRecords();
// 声明Map,封装total和records数据
//方法一使用Map
/* Map<String,Object> map = new HashMap<>();
map.put("total",total);
map.put("records",records);*/
// return R.success(map);
//封装一个PageResults对象
//方法二封装成类
PageResults<List<User>> pageResults = new PageResults<>();
pageResults.setTotal(total);
pageResults.setRecords(records);
return R.success(pageResults);
}
@PostMapping("/pageLikePhone")
public R pageLikePhone(@Valid @RequestBody UserPageDto dto){
//创建条件构造器对象
LambdaQueryWrapper<User> query = Wrappers.lambdaQuery(User.class);
//实现模糊查询
query.like(User::getPhone,dto.getPhone());
//获取当前页
Long current = dto.getDto().getCurrent();
//获取一个页面中有几条数据
Long size = dto.getDto().getSize();
IPage<User> page = new Page<>(current,siz);
//调用service方法
IPage<User> pageNew = userService.page(page, quer);
PageResults<List<User>> results = new PageResults<>();
results.setTotal(pageNew.getTotal());
results.setRecords(pageNew.getRecords());
return R.success(results);
}
2.数据校验
SpingBoot的校验框架完成数据开眼
Spring- boot-starter- validation
是通过Hibernate
框架完成的
2.1目标
把前端传参中的数据非空情况
/大于零
/手机号的合法性
提前判断处理
2.2使用方法
2.2.1导入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
2.2.2通过注解对数据设计校验规则
注解的名称 | 校验的作用 |
---|---|
@Empty | 检验目标的值是否是Null或"" |
@NotEmpty | 检验目标是否是Null或"" , 或检验目标的集合成员是否为空,常用 |
@NotNull | 检验目标是否是Null |
@Pattern(regexp = “”) | 检验目标是否符合正则规则,是最严格的校验方式 |
@Min | 检验目标的范围最小值 |
@Max | 检验目标的范围最大值 |
@NotEmpty(message = "用户手机号不能为空")
@Pattern(regexp = "^1[3-9]\\d{9}$",message = "用户手机号格式错误")
private String pho
@NotEmpty(message = "用户密码不能为空")
private String pwd;
2.2.3开启校验的注解@Valid
@PostMapping("/login")
public R login(@Valid @RequestBody UserLoginDto dto) throws BizException{
UserVo userVo = userService.login(dto);
return R.success(userVo);
}
2.2.4完善全局异常处理器
@ExceptionHandler(MethodArgumentNotValidException.class)
public R ValidException(MethodArgumentNotValidException e){
List<ObjectError> allErrors = e.getBindingResult().getAllErrors();
StringBuilder builder = new StringBuilder();
allErrors.forEach(objectError -> {
builder.append(objectError.getDefaultMessage());
builder.append(",");
String substring = builder.substring(0, builder.length() - 1);
return R.failed(substring);
}
3.MP使用代码生成器
3.1添加依赖
<!--mp的逆向工程生成器-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-generator</artifactId>
<version>3.5.1</version>
</dependency>
<!-- 模板引擎 -->
<dependency>
<groupId>org.apache.velocity</groupId>
<artifactId>velocity-engine-core</artifactId>
<version>2.0</version>
</dependency>
3.2执行生成
public class MPGenerator {
public static void main(String[] args) {
// 把连接url改成适配自己数据库的方式
String url = "jdbc:mysql://localhost:3306/agriculture? characterEncoding=UTF8&serverTimezone=Asia/Shanghai";
String username = "root";
String password = "12345678";
FastAutoGenerator.create(url, username, password)
// 基础全局配置
.globalConfig(builder -> {
builder.author("benson") // 设置作者,出现在文档注释中
.commentDate("yyyy-MM-dd")
.enableSwagger() // 开启 swagger 模式,给实体类pojo/controller添 加swagger的注解
.fileOverride() // 覆盖已生成文件
.outputDir("/Users/boboyay/Desktop/generator"); // 指定输出目录
})
// 包的配置
.packageConfig(builder -> {
builder.parent("com.gxa") // 设置父包名
.moduleName("agriculture") // 设置父包模块名
// mapper文件创建的目录
.mapper("mapper")
// 设置实体类包名
.entity("entity.pojo")
// 设置mapperXml生成路径
.pathInfo(Collections.singletonMap(OutputFile.mapperXml,
"/Users/boboyay/Desktop/generator"));
})
// 策略配置
.strategyConfig(builder -> {
// 指定哪些数据表要进行逆向工程的创建(pojo/mapper/service/controller)
// 选择表的时候应该选择单表(对应实体)
// 设置需要生成的表名, 注意: 关系表(多表查询的中间表)不需要
// 视图是否可以自动生成代码?
builder.addInclude("tb_user")
// 指定数据表的默认前缀,生成实体类时会忽略: tb_user-> User
.addTablePrefix("tb_", "sys_", "gxa_", "t_")
.serviceBuilder() //service策略
.formatServiceFileName("%sService") // 设置接口名不带I前 缀,UserService
.formatServiceImplFileName("%sServiceImpl") // UserServiceImpl
.entityBuilder() //实体类策略
.enableLombok() // 开启lombok
.enableTableFieldAnnotation() // 开启字段注解
.controllerBuilder() // controller策略
.enableRestStyle() //开启RestController
;
})
// .templateEngine(new FreemarkerTemplateEngine()) // 使用Freemarker引擎模板,默认的是Velocity引擎模板
.execute();
}
}
拓展
1.@GetMapping和PostMapping注解
@GetMapping
和 @PostMapping
是 Spring 框架中常用的注解,用于定义处理 HTTP GET 和 POST 请求的方法。
-
@GetMapping
注解:@GetMapping
注解用于将 HTTP GET 请求映射到特定的处理方法上。- 通常用于处理获取数据、显示页面等与获取资源相关的操作。
- 可以指定路径,参数,请求头等条件来匹配请求。
- 示例:
@GetMapping("/hello") public String sayHello() { return "Hello, World!"; }
-
@PostMapping
注解:@PostMapping
注解用于将 HTTP POST 请求映射到特定的处理方法上。- 通常用于处理提交数据、表单提交等与提交资源相关的操作。
- 可以指定路径,参数,请求头等条件来匹配请求。
- 示例:
@PostMapping("/submit") public String submitForm(@RequestBody Form form) { // 处理提交的表单数据 return "Form submitted successfully"; }
在使用这两个注解时,需要在 Spring Boot 应用程序的控制器类中添加相应的方法,并根据实际需求定义方法的逻辑。这样可以使得处理不同类型的 HTTP 请求变得简单和直观。
2.String、StringBuilder、StringBuffer的区别
String
、StringBuilder
和 StringBuffer
是 Java 中用于处理字符串的三种不同类,它们之间有以下区别:
-
String
:String
是不可变类,一旦创建就不能被修改。- 对
String
对象进行操作时,实际上是创建了一个新的String
对象,原始的String
对象不会改变。 - 适用于字符串不经常变化的情况,如字符串常量、配置信息等。
-
StringBuilder
:StringBuilder
是可变类,可以动态修改其内容。- 对
StringBuilder
对象进行操作时,不会创建新的对象,而是直接在原始对象上进行修改。 - 适用于需要频繁修改字符串内容的情况,如拼接字符串、构建动态内容等。
-
StringBuffer
:StringBuffer
也是可变类,类似于StringBuilder
,但是StringBuffer
是线程安全的,所有方法都是同步的。- 在多线程环境下,使用
StringBuffer
可以避免线程安全问题。 - 适用于多线程环境下需要频繁修改字符串内容的情况。
总结:
- 如果字符串内容不需要改变,使用
String
; - 如果字符串内容需要频繁改变且不涉及多线程,使用
StringBuilder
; - 如果字符串内容需要频繁改变且涉及多线程,使用
StringBuffer
。