分页查询
分析
要想从数据库中进行分页查询,我们要使用LIMIT
关键字,格式为:limit 开始索引 每页显示的条数
假设一页想展示10条数据
查询第1页数据的SQL语句是:
select * from emp limit 0,10;查询第2页数据的SQL语句是:
select * from emp limit 10,10;查询第3页的数据的SQL语句是:
select * from emp limit 20,10;观察以上SQL语句,发现: 开始索引一直在改变 , 每页显示条数是固定的
开始索引的计算公式: 开始索引 = (当前页码 - 1) * 每页显示条数
得到规律:开始索引 = (当前页码 - 1) * 每页显示条数
前端在请求服务端时,传递的参数
-
当前页码 page
-
每页显示条数 pageSize
后端需要响应什么数据给前端
-
所查询到的数据列表(存储到List 集合中)
-
总记录数
功能开发
封装PageBean对象
@Data
@NoArgsConstructor
@AllArgsConstructor
public class PageBean {
private Long total; //总记录数
private List rows; //当前页数据列表
}
Controller层
@RequestParam(defaultValue="默认值") //设置请求参数默认值
@Slf4j
@RestController
@RequestMapping("/emps")
public class EmpController {@Autowiredprivate EmpService empService;//条件分页查询@GetMappingpublic Result page(@RequestParam(defaultValue = "1") Integer page,@RequestParam(defaultValue = "10") Integer pageSize) {//记录日志log.info("分页查询,参数:{},{}", page, pageSize);//调用业务层分页查询功能PageBean pageBean = empService.page(page, pageSize);//响应return Result.success(pageBean);}
}
Service层
public interface EmpService {/*** 条件分页查询* @param page 页码* @param pageSize 每页展示记录数* @return*/PageBean page(Integer page, Integer pageSize);
}
实现类
@Slf4j
@Service
public class EmpServiceImpl implements EmpService {@Autowiredprivate EmpMapper empMapper;@Overridepublic PageBean page(Integer page, Integer pageSize) {//1、获取总记录数Long count = empMapper.count();//2、获取分页查询结果列表Integer start = (page - 1) * pageSize; //计算起始索引 , 公式: (页码-1)*页大小List<Emp> empList = empMapper.list(start, pageSize);//3、封装PageBean对象PageBean pageBean = new PageBean(count , empList);return pageBean;}
}
Mapper层
@Mapper
public interface EmpMapper {//获取总记录数@Select("select count(*) from emp")public Long count();//获取当前页的结果列表@Select("select * from emp limit #{start}, #{pageSize}")public List<Emp> list(Integer start, Integer pageSize);
}
分页插件 PageHelper
MyBatis 分页插件 PageHelper 如果你也在用 MyBatis,建议尝试该分页插件,这一定是最方便使用的分页插件。分页插件支持任何复杂的单表、多表分页。https://pagehelper.github.io/ PageHelper是一个MyBatis的分页插件,用于自动完成分页查询的工作。它通过简化分页查询的开发过程,减轻了开发人员在实现分页功能时的负担。PageHelper的使用流程通常包括引入依赖、配置插件、以及在代码中调用相应的方法来实现分页查询。
实现:
pom.xml引入依赖
<dependency><groupId>com.github.pagehelper</groupId><artifactId>pagehelper-spring-boot-starter</artifactId><version>1.4.6</version>
</dependency>
EmpMapper
@Mapper
public interface EmpMapper {//获取当前页的结果列表@Select("select * from emp")public List<Emp> page(Integer start, Integer pageSize);
}
EmpServiceImpl
@Override
public PageBean page(Integer page, Integer pageSize) {// 设置分页参数PageHelper.startPage(page, pageSize); // 执行分页查询List<Emp> empList = empMapper.list(name,gender,begin,end); // 获取分页结果Page<Emp> p = (Page<Emp>) empList; //封装PageBeanPageBean pageBean = new PageBean(p.getTotal(), p.getResult()); return pageBean;
}
文件上传
前端完成代码(例)
<form action="/upload" method="post" enctype="multipart/form-data">姓名: <input type="text" name="username"><br>年龄: <input type="text" name="age"><br>头像: <input type="file" name="image"><br><input type="submit" value="提交">
</form>
传文件的原始form表单,要求表单必须具备以下三点(上传文件页面三要素):
-
表单必须有file域,用于选择要上传的文件
-
表单提交方式必须为POST,通常上传的文件会比较大,所以需要使用 POST 提交方式
-
表单的编码类型enctype必须要设置为:multipart/form-data。普通默认的编码格式是不适合传输大型的二进制数据的,所以在文件上传时,表单的编码格式必须设置为multipart/form-data
本地存储上传
代码实现:
-
在服务器本地磁盘上创建images目录,用来存储上传的文件(例:E盘创建images目录)
-
使用MultipartFile类提供的API方法,把临时文件转存到本地磁盘目录下
Controller层
@Slf4j
@RestController
public class UploadController {@PostMapping("/upload")public Result upload(String username, Integer age, MultipartFile image) throws IOException {log.info("文件上传:{},{},{}",username,age,image);//获取原始文件名String originalFilename = image.getOriginalFilename();//将文件存储在服务器的磁盘目录image.transferTo(new File("E:/images/"+originalFilename));return Result.success();}}
由于我们是使用原始文件名作为所上传文件的存储名字,当我们再次上传一个名为1.jpg文件时,发现会把之前已经上传成功的文件覆盖掉。 为保证每次上传文件时文件名都唯一的(使用UUID获取随机文件名)
@Slf4j
@RestController
public class UploadController {@PostMapping("/upload")public Result upload(String username, Integer age, MultipartFile image) throws IOException {log.info("文件上传:{},{},{}",username,age,image);//获取原始文件名String originalFilename = image.getOriginalFilename();//构建新的文件名String extname = originalFilename.substring(originalFilename.lastIndexOf("."));//文件扩展名String newFileName = UUID.randomUUID().toString()+extname;//随机名+文件扩展名//将文件存储在服务器的磁盘目录image.transferTo(new File("E:/images/"+newFileName));return Result.success();}}
application.properties/yml
#配置单个文件最大上传大小
spring.servlet.multipart.max-file-size=10MB#配置单个请求最大上传大小(一次请求可以上传多个文件)
spring.servlet.multipart.max-request-size=100MBspring:servlet:multipart.max-file-size: 10MBmultipart.max-request-size: 100MB
大小可根据需求更改
阿里云OSS上传
参照官方提供的SDK,改造一下,即可实现文件上传功能:
public class AliOssTest {public static void main(String[] args) throws Exception {// Endpoint以华东1(杭州)为例,其它Region请按实际情况填写。String endpoint = "oss-cn-shanghai.aliyuncs.com";// 阿里云账号AccessKey拥有所有API的访问权限,风险很高。强烈建议您创建并使用RAM用户进行API访问或日常运维,请登录RAM控制台创建RAM用户。String accessKeyId = "LTAI5t9MZK8iq5T2Av5GLDxX";String accessKeySecret = "C0IrHzKZGKqU8S7YQcevcotD3Zd5Tc";// 填写Bucket名称,例如examplebucket。String bucketName = "web-framework01";// 填写Object完整路径,完整路径中不能包含Bucket名称,例如exampledir/exampleobject.txt。String objectName = "1.jpg";// 填写本地文件的完整路径,例如D:\\localpath\\examplefile.txt。// 如果未指定本地路径,则默认从示例程序所属项目对应本地路径中上传文件流。String filePath= "C:\\Users\\Administrator\\Pictures\\1.jpg";// 创建OSSClient实例。OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);try {InputStream inputStream = new FileInputStream(filePath);// 创建PutObjectRequest对象。PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, objectName, inputStream);// 设置该属性可以返回response。如果不设置,则返回的response为空。putObjectRequest.setProcess("true");// 创建PutObject请求。PutObjectResult result = ossClient.putObject(putObjectRequest);// 如果上传成功,则返回200。System.out.println(result.getResponse().getStatusCode());} catch (OSSException oe) {System.out.println("Caught an OSSException, which means your request made it to OSS, "+ "but was rejected with an error response for some reason.");System.out.println("Error Message:" + oe.getErrorMessage());System.out.println("Error Code:" + oe.getErrorCode());System.out.println("Request ID:" + oe.getRequestId());System.out.println("Host ID:" + oe.getHostId());} catch (ClientException ce) {System.out.println("Caught an ClientException, which means the client encountered "+ "a serious internal problem while trying to communicate with OSS, "+ "such as not being able to access the network.");System.out.println("Error Message:" + ce.getMessage());} finally {if (ossClient != null) {ossClient.shutdown();}}}
}
在以上代码中,需要替换的内容为:
-
accessKeyId:阿里云账号AccessKey
-
accessKeySecret:阿里云账号AccessKey对应的秘钥
-
bucketName:Bucket名称
-
objectName:对象名称,在Bucket中存储的对象的名称
-
filePath:文件路径
实现:
引入阿里云OSS上传文件工具类(由官方的示例代码改造而来)
@Component
public class AliOSSUtils {private String endpoint = "https://oss-cn-shanghai.aliyuncs.com";private String accessKeyId = "LTAI5t9MZK8iq5T2Av5GLDxX";private String accessKeySecret = "C0IrHzKZGKqU8S7YQcevcotD3Zd5Tc";private String bucketName = "web-framework01";/*** 实现上传图片到OSS*/public String upload(MultipartFile multipartFile) throws IOException {// 获取上传的文件的输入流InputStream inputStream = multipartFile.getInputStream();// 避免文件覆盖String originalFilename = multipartFile.getOriginalFilename();String fileName = UUID.randomUUID().toString() + originalFilename.substring(originalFilename.lastIndexOf("."));//上传文件到 OSSOSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);ossClient.putObject(bucketName, fileName, inputStream);//文件访问路径String url = endpoint.split("//")[0] + "//" + bucketName + "." + endpoint.split("//")[1] + "/" + fileName;// 关闭ossClientossClient.shutdown();return url;// 把上传到oss的路径返回}
}
修改UploadController代码:
@Slf4j
@RestController
public class UploadController {@Autowiredprivate AliOSSUtils aliOSSUtils;@PostMapping("/upload")public Result upload(MultipartFile image) throws IOException {//调用阿里云OSS工具类,将上传上来的文件存入阿里云String url = aliOSSUtils.upload(image);//将图片上传完成后的url返回,用于浏览器回显展示return Result.success(url);}}