分頁查詢
分析
要想從數據庫中進行分頁查詢,我們要使用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);}}