基于Spring Boot框架的分页查询和文件上传

分页查询

分析

要想从数据库中进行分页查询,我们要使用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 {

    @Autowired
    private EmpService empService;

    //条件分页查询
    @GetMapping
    public 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 {
    @Autowired
    private EmpMapper empMapper;

    @Override
    public 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,建议尝试该分页插件,这一定是最方便使用的分页插件。分页插件支持任何复杂的单表、多表分页。icon-default.png?t=N7T8https://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;   
    //封装PageBean
    PageBean 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

本地存储上传

代码实现:

  1. 在服务器本地磁盘上创建images目录,用来存储上传的文件(例:E盘创建images目录)

  2. 使用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=100MB


spring:
  servlet:
    multipart.max-file-size: 10MB
    multipart.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("."));

        //上传文件到 OSS
        OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
        ossClient.putObject(bucketName, fileName, inputStream);

        //文件访问路径
        String url = endpoint.split("//")[0] + "//" + bucketName + "." + endpoint.split("//")[1] + "/" + fileName;

        // 关闭ossClient
        ossClient.shutdown();
        return url;// 把上传到oss的路径返回
    }
}

 修改UploadController代码:

@Slf4j
@RestController
public class UploadController {

    @Autowired
    private AliOSSUtils aliOSSUtils;

    @PostMapping("/upload")
    public Result upload(MultipartFile image) throws IOException {
        //调用阿里云OSS工具类,将上传上来的文件存入阿里云
        String url = aliOSSUtils.upload(image);
        //将图片上传完成后的url返回,用于浏览器回显展示
        return Result.success(url);
    }
    
}
  • 61
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
1. 系统需求 该个人博客系统需要支持以下功能: - 注册和登录功能。 - 文章的发布、修改、删除和查看功能。 - 评论功能。 - 分类和标签管理功能。 - 搜索功能。 - 友情链接功能。 - 管理员后台管理功能。 2. 技术选型 - 后端框架Spring Boot - 数据库:MySQL - 前端框架:Vue - 前端UI库:ElementUI - 数据交互:RESTful API 3. 系统架构 该个人博客系统采用前后端分离的架构,前端使用Vue框架后端使用Spring Boot框架。前后端之间通过RESTful API进行数据交互。 后端主要包含以下几个模块: - 用户模块:包含用户注册、登录、密码修改等功能。 - 文章模块:包含文章的增删改查、分页查询等功能。 - 评论模块:包含评论的增删改查功能。 - 分类和标签模块:包含分类和标签的增删改查功能。 - 搜索模块:包含搜索文章和评论的功能。 - 友情链接模块:包含友情链接的增删改查功能。 - 管理员模块:包含管理员登录、文章管理、分类管理、标签管理、评论管理等功能。 4. 数据库设计 系统需要存储的数据包括用户信息、文章信息、评论信息、分类信息、标签信息、友情链接信息等。 - 用户表(user):存储用户的基本信息,包括用户ID、用户名、密码、邮箱等字段。 - 文章表(article):存储文章的详细信息,包括文章ID、标题、内容、发布时间、分类ID、标签ID等字段。 - 评论表(comment):存储评论的详细信息,包括评论ID、评论内容、评论时间、文章ID、用户ID等字段。 - 分类表(category):存储文章的分类信息,包括分类ID、分类名称等字段。 - 标签表(tag):存储文章的标签信息,包括标签ID、标签名称等字段。 - 友情链接表(link):存储友情链接的信息,包括链接ID、链接名称、链接地址等字段。 5. API设计 - 注册接口:POST /api/user/register - 登录接口:POST /api/user/login - 文章列表接口:GET /api/article - 文章详情接口:GET /api/article/{id} - 文章发布接口:POST /api/article - 文章更新接口:PUT /api/article/{id} - 文章删除接口:DELETE /api/article/{id} - 评论列表接口:GET /api/comment - 评论详情接口:GET /api/comment/{id} - 评论发布接口:POST /api/comment - 评论更新接口:PUT /api/comment/{id} - 评论删除接口:DELETE /api/comment/{id} - 分类列表接口:GET /api/category - 分类详情接口:GET /api/category/{id} - 分类发布接口:POST /api/category - 分类更新接口:PUT /api/category/{id} - 分类删除接口:DELETE /api/category/{id} - 标签列表接口:GET /api/tag - 标签详情接口:GET /api/tag/{id} - 标签发布接口:POST /api/tag - 标签更新接口:PUT /api/tag/{id} - 标签删除接口:DELETE /api/tag/{id} - 搜索接口:GET /api/search?q={keyword} - 友情链接列表接口:GET /api/link - 友情链接详情接口:GET /api/link/{id} - 友情链接发布接口:POST /api/link - 友情链接更新接口:PUT /api/link/{id} - 友情链接删除接口:DELETE /api/link/{id} 6. 前端页面设计 - 首页:展示最新文章、分类、标签、友情链接等。 - 文章列表页:展示文章列表,支持分页和搜索功能。 - 文章详情页:展示文章详细信息和评论列表,支持评论功能。 - 分类列表页:展示分类列表,支持添加、编辑和删除分类。 - 标签列表页:展示标签列表,支持添加、编辑和删除标签。 - 友情链接页:展示友情链接列表,支持添加、编辑和删除友情链接。 - 登录页:用户登录页面。 - 注册页:用户注册页面。 7. 系统部署 - 后端部署:使用Maven构建Spring Boot项目,打成jar包,然后使用java -jar命令启动项目。 - 前端部署:使用npm安装Vue项目依赖,然后使用npm run build命令打包项目。 - 数据库部署:使用MySQL数据库,将数据库脚本导入数据库即可。 总结 基于Spring Boot和Vue的个人博客系统设计,实现了用户的注册和登录、文章的发布、修改、删除和查看、评论、分类和标签管理、搜索、友情链接、管理员后台管理等功能。该系统采用前后端分离的架构,通过RESTful API进行数据交互,实现了系统的高效和灵活。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值