曾经面试有个人问我分页的几种实现方式和框架这些,现在才回,有点晚,这里只用了一种实现方式,利用spring boot的jpa中page对象的实现。还有数据库自带的limit语句,和SSM框架中的mybatis语句中常用,以后遇到了更新这几种实现方式,这种最方便。持续关注哦!
这里将几个实战例子,从数据库到前台一口气实现。
项目文件目录
效果预览
list分页
修改
新增
操作友好提示
一、使用 page对象的实现步骤
1. 创建实体对象类User
package com.youngpeng.blog.entity;
import lombok.Data;
import org.hibernate.annotations.DynamicUpdate;
import javax.persistence.Entity;
import javax.persistence.Id;
import java.util.Date;
@Entity
@Data
@DynamicUpdate
public class User {
@Id
private String id;
private String name;
private String email;
// @DynamicUpdate 针对时间自动更新而言
private Date createTime;
private Date updateTime;
// 构造函数
public User() {
}
public User(String id, String name, String email) {
this.id = id;
this.name = name;
this.email = email;
}
}
2. 写数据库代理层接口UserRepository (JPA/ DAO/ REPOSITORY)
package com.youngpeng.blog.repository;
import com.youngpeng.blog.entity.User;
import org.springframework.data.jpa.repository.JpaRepository;
/**
* 增删改查的接口,一般别写
*/
public interface UserRepository extends JpaRepository<User,String> {
}
3. 写service接口UserService
package com.youngpeng.blog.service;
import com.youngpeng.blog.entity.User;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
public interface UserService {
User save(User user);
void deleteById(String id);
User findOne(String id);
Page<User> findAll(Pageable pageable);
}
4. 写UserService 接口的实现逻辑UserServiceImpl
package com.youngpeng.blog.service.serviceImpl;
import com.youngpeng.blog.entity.User;
import com.youngpeng.blog.repository.UserRepository;
import com.youngpeng.blog.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class UserServiceImpl implements UserService {
@Autowired
private UserRepository userRepository;
@Override
public User save(User user) {
return userRepository.save(user);
}
@Override
public void deleteById(String id) {
userRepository.delete(id);
}
@Override
public User findOne(String id) {
return userRepository.findOne(id);
}
@Override
public Page<User> findAll(Pageable pageable) {
// 1. 调用JPA分页查询的方法
Page<User> userPage = userRepository.findAll(pageable);
// 2. 转换为list,
List<User> userList = userPage.getContent();
// 3. 返回
// public PageImpl(List<T> content, Pageable pageable, long total) {}
// public PageImpl(List<T> content) {}
return new PageImpl<>(userList, pageable, userPage.getTotalElements());
}
}
5. 写Controller层的方法调用,这是前后端交互的接口,URL首先进入该层处理
package com.youngpeng.blog.controller;
import com.youngpeng.blog.entity.User;
import com.youngpeng.blog.form.CreateUser;
import com.youngpeng.blog.service.UserService;
import com.youngpeng.blog.utils.GeneraterKey;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.stereotype.Controller;
import org.springframework.util.StringUtils;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;
import javax.validation.Valid;
import java.util.List;
import java.util.Map;
@Controller
@RequestMapping("/user")
@Slf4j
public class UserController {
@Autowired
private UserService userService;
/**
* 以分页的形式显示用户列表信息
* 1. 接收参数page, size.
* 2. 初始化pagerequest,
* 3. 查询
* 4. 返回结果
*/
@GetMapping("/list")
public ModelAndView userlist(@RequestParam(value = "page" ,defaultValue = "1") int page,
@RequestParam(value = "size" ,defaultValue = "2") int size,
Map<String, Object> map){
// 初始化pagerequest
PageRequest pageRequest = new PageRequest(page-1, size);
// 调用service 层 的 page 接口查询
Page<User> userPage = userService.findAll(pageRequest);
map.put("userPage", userPage);
map.put("currentPage",page);
map.put("size", size);
return new ModelAndView("/user/list", map);
}
/**创建一个空对象出来存储
* 1. 首先判断URL中有无ID号
* 2. 有 - 根据ID查询数据。 无 - 自动生成ID号赋值
* 3. 将前端传来的数据拷贝到对象中,无,显示空,有值- 则修改
*
* @param createUser
* @param bindingResult
* @param map
* @return
*/
@GetMapping("/create")
public ModelAndView create(@Valid CreateUser createUser,
BindingResult bindingResult,
Map<String, Object> map){
User userNew = new User();
//判断前端数据正误
if (bindingResult.hasErrors()){
map.put("msg", bindingResult.getFieldError().getDefaultMessage());
map.put("url", "/user/list");
return new ModelAndView("common/error",map);
}
// 判断有无ID号
if (StringUtils.isEmpty(createUser.getId() )){
// 新建 -- 设置id 号
userNew.setId(GeneraterKey.genUniqueKey());
}else {
// 修改 -- 查询出来显示
userNew = userService.findOne(createUser.getId());
}
// 下面是同一的拷贝
// createUser.setName(userNew.getName()); --- error 反了
try {
userNew.setName(createUser.getName());
userNew.setEmail(createUser.getEmail());
/**
* 这里更改之后千万别忘了保存到数据库
*/
userService.save(userNew);
}catch (Exception e){
// log.error("[注册、修改操作发生错误]{}",e);
map.put("msg", "[注册、修改操作发生错误]");
map.put("url", "/user/list");
return new ModelAndView("common/error",map);
}
map.put("user", userNew);
map.put("url", "/user/list");
return new ModelAndView("/common/success",map);
}
/**
* 新增和修改的页面都在这个页面进行单独操作
* @param id
* @param map
* @return
*/
@GetMapping("/index")
public ModelAndView index(@RequestParam(value = "id", required = false) String id,
Map<String, Object> map){
// 如果有id值传进来,就打包查询返回
User user = new User();
if ( !StringUtils.isEmpty(id) ){
user = userService.findOne(id);
}
map.put("userInfo", user);
return new ModelAndView("/user/index", map);
}
@GetMapping("/delete")
public ModelAndView delete(@RequestParam(value = "id") String id,
Map<String, Object> map){
try{
// 直接执行删除操作
userService.deleteById(id);
}catch (Exception e){
map.put("msg", "删除发生错误");
map.put("url", "/user/list");
return new ModelAndView("common/error",map);
}
map.put("msg", "删除成功");
map.put("url", "/user/list");
return new ModelAndView("common/success",map);
}
}
6. 写前台代码 list.ftl
这里注意,list显示用户,但是单独的用户操作写在index页面中,细细评味其中逻辑
<link href="https://cdn.bootcss.com/twitter-bootstrap/3.3.1/css/bootstrap.min.css"
rel="stylesheet"/>
<h1 style="text-align: center">用户信息列表</h1>
<#--表格主体-->
<div class="container">
<div class="row clearfix">
<div class="col-md-12 column">
<table class="table table-bordered">
<thead>
<tr>
<th>编号</th>
<th>姓名</th>
<th>邮箱</th>
<th>创建时间</th>
<th>修改时间</th>
<th colspan="2">操作</th>
</tr>
</thead>
<tbody>
<#--一列一用户。 每一列都是循环-->
<#list userPage.content as userPage>
<tr>
<td>${userPage.id}</td>
<td>${userPage.name}</td>
<td>${userPage.email}</td>
<td>${userPage.createTime}</td>
<td>${userPage.updateTime}</td>
<td><a href="/user/index?id=${userPage.id}">修改</a></td>
<td><a href="/user/delete?id=${userPage.id}">删除</a></td>
</tr>
</#list>
</tbody>
</table>
</div>
</div>
</div>
<#--新增一个用户-->
<button type="button" ><a href="/user/index">新增一个用户</a></button>
<#-- 分页切换按钮-->
<div class="container">
<div class="row clearfix">
<div class="col-md-12 column">
<ul class="pagination pagination-lg pull-right ">
<#--如果是第一页,禁止点击
否则链接到上一页-->
<#if currentPage lte 1>
<li class="disabled"><a href="#">上一页</a></li>
<#else>
<li><a href="/user/list?page=${currentPage-1}&size=${size}">上一页</a></li>
</#if>
<#-- 页数应该动态的增加
如果是当前页 - 禁止点击
负责点击链接到相应的页面-->
<#list 1..userPage.getTotalPages() as index>
<#if currentPage == index>
<li class="disabled"><a href="#">${index}</a></li>
<#else>
<li><a href="/user/list?page=${index}&size=${size}">${index}</a></li>
</#if>
</#list>
<#if currentPage gte userPage.getTotalPages()>
<li class="disabled"><a href="#">下一页</a></li>
<#else>
<li ><a href="/user/list?page=${currentPage+1}&size=${size}">下一页</a></li>
</#if>
</ul>
</div>
</div>
</div>
7.写index.ftl
<#--主要内容-->
<div id="page-content-wrapper">
<div class="container">
<div class="row clearfix">
<div class="col-md-12 column">
<form role="form" method="Get" action="/user/create">
<div class="form-group">
<label>名称:</label>
<input type="text" class="form-control" name="name" value="${(userInfo.name)!""}"/>
<label>邮箱:</label>
<input type="text" class="form-control" name="email" value="${(userInfo.email)!""}"/>
</div>
<input type="hidden" class="form-control" name="id" value="${(userInfo.id)!""}"/>
<button type="submit" class="btn btn-default">提交</button>
</form>
</div>
</div>
</div>
8. 友好提示页面 error 、 success
<html>
<head>
<meta charset="UTF-8">
<link href="https://cdn.bootcss.com/twitter-bootstrap/3.0.1/css/bootstrap.min.css" rel="stylesheet">
<title>操作发生错误</title>
</head>
<body>
<div class="container">
<div class="row clearfix">
<div class="col-md-12 column">
<div class="alert alert-dismissable alert-warning">
<button type="button" class="close" data-dismiss="alert" aria-hidden="true">×</button>
<h4>发生错误!</h4>
<strong>${msg!""}</strong>
<a id="jump" href="${url}" class="alert-link">3</a><span>秒后自动跳转原来页面</span>
</div>
</div>
</div>
</div>
</body>
<#--setTimeout(location.href="${url}",3000);-->
<script type="text/javascript">
onload=function(){
setInterval(go, 1000);
};
var x=3; //利用了全局变量来执行
function go(){
x--;
if(x>0){
document.getElementById("jump").innerHTML=x; //每次设置的x的值都不一样了。
}else{
location.href="${url}";
}
}
</script>
</html>