Spring Data Jpa+SpringMVC+Jquery.pagination.js 实现分页 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
Sign Up Now
For Existing Member  Sign In
javahih
V2EX    Java

Spring Data Jpa+SpringMVC+Jquery.pagination.js 实现分页

  •  
  •   javahih Dec 26, 2017 4323 views
    This topic created in 3046 days ago, the information mentioned may be changed or developed.

    本博客介绍基于 Spring Data 这款 orm 框架加上 Jquery.pagination 插件实现的分页功能。

    本博客是基于一款正在开发中的 github 开源项目的,项目代码地址: https://github.com/u014427391/jeeplatform 欢迎 star(收藏)或者可以下载去学习,还在开发...

    介绍一下 Spring Data 框架 spring Data : Spring 的一个子项目。用于简化数据库访问,支持 NoSQL 和 关系数据存储。 下面给出 SpringData 项目所支持 NoSQL 存储:

    • MongoDB (文档数据库)
    • Neo4j (图形数据库)
    • Redis (键 /值存储)
    • Hbase (列族数据库)

    SpringData 项目所支持的关系数据存储技术:

    • JDBC
    • JPA

    JPA Spring Data : 致力于减少数据访问层 (DAO) 的开发量。开发者只要写好持久层接口就好,然后其它的框架会帮程序员实现。

    开发步骤: [ Spring Data 实现数据获取] 本项目是采用 maven 的,所以可以参考一下项目的 maven 配置:

    设计好数据库,编写一个实体类: 这里写图片描述

    package org.muses.jeeplatform.model.entity; import java.util.Date; import java.util.Set; import javax.persistence.CascadeType; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.FetchType; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.JoinColumn; import javax.persistence.JoinTable; import javax.persistence.ManyToMany; import javax.persistence.Table; import javax.persistence.Temporal; import javax.persistence.TemporalType; /** * 用户信息的实体类 * @author Nicky */ @Entity @Table(name="sys_user") public class User { /** 用户 Id**/ private int id; /** 用户名**/ private String username; /** 用户密码**/ private String password; /** 手机号**/ private int phone; /** 性别**/ private String sex; /** 邮件**/ private String email; /** 备注**/ private String mark; /** 用户级别**/ private String rank; /** 最后一次时间**/ private Date lastLogin; /** 登录 ip**/ private String loginIp; /** 图片路径**/ private String imageUrl; /** 注册时间**/ private Date regTime; /** 账号是否被锁定**/ private Boolean locked = Boolean.FALSE; private Set<Role> roles; @GeneratedValue(strategy=GenerationType.IDENTITY) @Id public int getId() { return id; } public void setId(int id) { this.id = id; } @Column(unique=true,length=100,nullable=false) public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } @Column(length=100,nullable=false) public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public int getPhone() { return phone; } public void setPhone(int phone) { this.phOne= phone; } @Column(length=6) public String getSex() { return sex; } public void setSex(String sex) { this.sex = sex; } @Column(length=100) public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } @Column(length=30) public String getMark() { return mark; } public void setMark(String mark) { this.mark = mark; } @Column(length=10) public String getRank() { return rank; } public void setRank(String rank) { this.rank = rank; } @Temporal(TemporalType.DATE) public Date getLastLogin() { return lastLogin; } public void setLastLogin(Date lastLogin) { this.lastLogin = lastLogin; } @Column(length=100) public String getLoginIp() { return loginIp; } public void setLoginIp(String loginIp) { this.loginIp = loginIp; } @Column(length=100) public String getImageUrl() { return imageUrl; } public void setImageUrl(String imageUrl) { this.imageUrl = imageUrl; } @Temporal(TemporalType.DATE) @Column(nullable=false) public Date getRegTime() { return regTime; } public void setRegTime(Date regTime) { this.regTime = regTime; } public Boolean getLocked() { return locked; } public void setLocked(Boolean locked) { this.locked = locked; } } 

    编写接口实现 Spring Data 框架的 PagingAndSortingRepository 接口

    package org.muses.jeeplatform.repository; import org.muses.jeeplatform.model.entity.User; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.PagingAndSortingRepository; import org.springframework.data.repository.query.Param; import java.util.Date; public interface UserRepository extends PagingAndSortingRepository<User, Integer> { /*User findByUsername(String username); @Query("from User u where u.username=:username and u.password=:password") User findByUsernameAndPassword(@Param("username") String username, @Param("password") String password); @Query("from User u where u.id=:id") User findById(@Param("id") int id); @Query("from User u where date_format(u.lastLogin,'yyyy-MM-dd') between date_format((:startDate),'yyyy-MM-dd') and date_format((:endDate),'yyyy-MM-dd')") Page<User> searchU(@Param("startDate")Date startDate,@Param("endDate")Date endDate, Pageable pageable); */ } 

    业务类实现:

    package org.muses.jeeplatform.service; import java.util.*; import org.muses.jeeplatform.model.entity.User; import org.muses.jeeplatform.repository.UserRepository; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Sort; import org.springframework.data.jpa.domain.Specification; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import javax.persistence.criteria.CriteriaBuilder; import javax.persistence.criteria.CriteriaQuery; /** * @description 用户信息管理的业务类 * @author Nicky * @date 2017 年 3 月 6 日 */ @Service public class UserService { @Autowired UserRepository userRepository; /** * 构建 PageRequest 对象 * @param num * @param size * @param asc * @param string * @return */ private PageRequest buildPageRequest(int num, int size, Sort.Direction asc, String string) { return new PageRequest(num-1, size,null,string); } /** * 获取所有的菜单信息并分页显示 * @param pageNo * 当前页面数 * @param pageSize * 每一页面的页数 * @return */ @Transactional public Page<User> findAll(int pageNo, int pageSize, Sort.Direction dir, String str){ PageRequest request = buildPageRequest(pageNo, pageSize, dir, str); Page<User> users = userRepository.findAll(request); return users; } } 

    控制类,采用 SpringMVC 框架,先编写一个 baseController,实现一些通用功能的封装:

    package org.muses.jeeplatform.web.controller; import javax.servlet.http.HttpServletRequest; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.web.context.request.RequestContextHolder; import org.springframework.web.context.request.ServletRequestAttributes; import org.springframework.web.servlet.ModelAndView; public class BaseController { Logger log = null; /** * 获取日志对象 * @return */ public Logger getInstance(){ if(log == null){ log = LoggerFactory.getLogger(BaseController.class); } return log; } /** * 得到 request 对象 */ public HttpServletRequest getRequest() { HttpServletRequest request = ((ServletRequestAttributes)RequestContextHolder.getRequestAttributes()).getRequest(); return request; } /** * 得到 ModelAndView */ public ModelAndView getModelAndView(){ return new ModelAndView(); } } 

    控制类实现:

    package org.muses.jeeplatform.web.controller; import net.sf.json.JSONArray; import net.sf.json.JSONObject; import net.sf.json.JsonConfig; import org.apache.commons.collections.map.HashedMap; import org.muses.jeeplatform.core.Constants; import org.muses.jeeplatform.core.ExcelViewWrite; import org.muses.jeeplatform.core.JavaEmailSender; import org.muses.jeeplatform.model.entity.User; import org.muses.jeeplatform.service.UserService; import org.muses.jeeplatform.utils.DateJsonValueProcessor; import org.muses.jeeplatform.utils.DateUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.Page; import org.springframework.data.domain.Sort; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; 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.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.PrintWriter; import java.util.*; /** * Created by Nicky on 2017/7/29. */ @RequestMapping("/user") @Controller public class UserController extends BaseController{ @Autowired UserService userService; /** * 查询所有管理员信息并分页显示 * @param request * @param response * @param model * @return */ @RequestMapping(value = "/queryAll",produces = "application/json;charset=") @ResponseBody public ModelAndView findAll(HttpServletRequest request, HttpServletResponse response, Model model){ //当前页 String pageIndexStr = request.getParameter("pageIndex"); //每一页的页数 int pageSize = Constants.PAGE_SIZE; ModelAndView mv = this.getModelAndView(); Page<User> userPage; if(pageIndexStr==null||"".equals(pageIndexStr)){ pageIndexStr = "0"; } int pageIndex = Integer.parseInt(pageIndexStr); userPage = userService.findAll(pageIndex+1, pageSize, Sort.Direction.ASC,"id"); mv.addObject("totalCount",userPage.getTotalElements()); mv.addObject("pageIndex",pageIndex); // JsonConfig cfg = new JsonConfig(); // cfg.setExcludes(new String[]{"handler","hibernateLazyInitializer"}); JsonConfig jcg = new JsonConfig(); jcg.registerJsonValueProcessor(Date.class, new DateJsonValueProcessor("yyyy-mm-dd")); JSONArray jsOnArray= JSONArray.fromObject(userPage.getContent(),jcg); //System.out.println(jsonArray.toString()); mv.addObject("users",jsonArray.toString()); mv.setViewName("admin/user/sys_user_list"); return mv; } } 

    [前端页面实现] 页面 View 实现,引用 jquery.pagination.js (分页 js ),跟 pagination.css (分页样式 css )。 可以去这里下载 http://www.cnblogs.com/knowledgesea/archive/2013/01/03/2841554.html

    <%@ page cOntentType="text/html; charset=" pageEncoding="utf-8"%> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> <%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt"%> <% String path = request.getContextPath(); String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/"; %> <!DOCTYPE html> <html lang="zh-CN"> <head> <base href="<%=basePath %>"> <meta charset="UTF-8" /> <meta http-equiv="X-UA-Compatible" cOntent="IE=edge"> <meta name="viewport" cOntent="width=device-width,initial-scale=1"> <title>Insert title here</title> <!-- bootstrap 样式--> <link type="text/css" rel="stylesheet" href="<%=basePath%>plugins/page/css/bootstrap-3.3.5.min.css" /> <!-- jquery.pagination 所需 CSS --> <link type="text/css" rel="stylesheet" href="<%=basePath%>plugins/page/css/pagination.css" /> <script type="text/Javascript" src="<%=basePath%>plugins/page/js/jquery.min.js"></script> <!-- jquery.pagination 所需 JS 注意必须放在 jquery.js 后面 --> <script type="text/Javascript" src="<%=basePath%>plugins/page/js/jquery.pagination.js"></script> <script type="text/Javascript"> /** 分页操作,使用 jquery.pagination 插件 add by nicky 20170729 start **/ //当前页 var pageIndex = Number(${pageIndex}); //数据量 var totalCount = Number(${totalCount}); $(document).ready(function () { //加入分页的绑定 $("#Pagination").pagination(totalCount, { callback : pageselectCallback, prev_text : '< 上一页', next_text: '下一页 >', items_per_page : 6, num_display_entries : 6, current_page : pageIndex, num_edge_entries : 1, link_to: "user/queryAll?pageIndex=__id__" //分页的 js 中会自动把"__id__"替换为当前的数。0 }); var html = ""; var data = ${users}; $.each(data,function(idx,obj){ var id = obj.id; var username = obj.username; var mark = obj.mark; var phOne= obj.phone; var email = obj.email; var lastLogin = obj.lastLogin; var loginIp = obj.loginIp; html += "<tr><td><input type='checkbox' name='id' id='id' value=" + id + " /></td>" + "<td>"+id+"</td>"+ "<td>"+username+"</td>"+ "<td>"+mark+"</td>"+ "<td>"+phone+"</td>"+ "<td>"+email+"</td>"+ "<td>"+lastLogin+"</td>"+ "<td>"+loginIp+"</td>"+ "<td><a href='Javascript:openEditDialog("+id+");' class='bounceIn'>配置角色</a>"+ "</tr>"; }); $("#content").append(html); }); //这个事件是在翻页时候用的 function pageselectCallback(index, jq) { } /** 分页操作,使用 jquery.pagination 插件 add by nicky 20170729 end **/ //checkbox 的全选 /反选 var isCheckAll = false; function doCheck(){ if(isCheckAll){ $("input[type='checkbox']").each(function(){ this.checked = false; }); isCheckAll = false; }else{ $("input[type='checkbox']").each(function(){ this.checked = true; }); isCheckAll = true; } } </script> </head> <body> <br> <div class="container-fluid"> <div class="row"> <div class="col-xs-12 col-md-12"> <div class="panel panel-default"> <div class="panel-body"> <form class="form-inline"> <input type="button" class="btn btn-default" value="发送邮件" Onclick="sendEmail();" /> <input type="button" class="btn btn-default" value="发送短信" Onclick="sendSms();" /> <input type="button" class="btn btn-default" value="导出 Excel 表" Onclick="exportExcel();" /> <br><br><!-- <input type="text" class="form-control" id="keyword" placeholder="请输入关键词"> &nbsp;&nbsp;&nbsp;&nbsp; 日期从<input type="text" class="form-control" placeholder="请输入开始日期" value="${startdate }" id="startDate" name="startdate" Onclick="WdatePicker({dateFmt:'yyyy-MM-dd' ,maxDate:'#F{$dp.$D(\'endDate\')}'});"/> 到<input type="text" class="form-control" placeholder="请输入结束日期" value="${enddate }" id="endDate" name="enddate" Onclick="WdatePicker({dateFmt:'yyyy-MM-dd' ,minDate:'#F{$dp.$D(\'startDate\')}'});" />&nbsp;&nbsp;&nbsp;&nbsp; <input type="button" class="btn btn-default" value="Search" Onclick="doSearch();"/>--> </form> <table class="table" id="mTable"> <thead> <tr> <th><input type="checkbox" Onclick="doCheck();" /></th> <th>序号</th> <th>用户名</th> <th>描述</th> <th>手机</th> <th>邮箱</th> <th>最近登录</th> <th>上次登录 IP</th> <th>操作</th> </tr> </thead> <tbody id="content"> </tbody> </table> <div id="Pagination" class="pagination"></div> <!-- demo --> </div> </div> </div> </div> </div> </body> </html> 

    前端页面展示: 这里写图片描述

    ok,本博客是基于一款正在开发中的 github 开源项目的,项目代码地址: https://github.com/u014427391/jeeplatform 欢迎 star(收藏)或者可以下载去学习,不过还在开发...

    15 replies    2017-12-26 22:01:44 +08:00
    evolify
        1
    evolify  
       Dec 26, 2017
    v2 上面都是不用 jq 的
    acrisliu
        2
    acrisliu  
       Dec 26, 2017
    V2 不建议全文转载,建议直接贴你 CSDN 博客链接就好了,虽然 V2 的排版比 CSDN 好看很多。(逃
    nicevar
        3
    nicevar  
       Dec 26, 2017
    这种系统还是采用 ExtJS 开发最方便,你这分页还能写出一篇文章,ExtJS 里面直接一个控件放进去就搞定了,所有的逻辑已经跟 jpa 无缝对接了,不用自己写一句代码
    jeffpan
        4
    jeffpan  
       Dec 26, 2017
    Spring MVC 太多冗余代码了,既然用 JPA,何不用 Spring Boot ?
    loveCoding
        5
    loveCoding  
       Dec 26, 2017   2
    这... 一个分页都能写篇文章啦
    jalena
        6
    jalena  
       Dec 26, 2017
    代码写的好。!
    gbin
        7
    gbin  
       Dec 26, 2017 via Android
    @loveCoding 都是从基础过来的
    jalena
        8
    jalena  
       Dec 26, 2017
    话说既然都用 jquery,为毛不直接再用个 table 框架,,人家都找好了轮子了嘛!
    loveCoding
        9
    loveCoding  
       Dec 26, 2017
    @gbin #7 哈哈 ,没有嘲讽的意思
    hantsy
        10
    hantsy  
       Dec 26, 2017
    好多年没见 JSP 了,我快十年没用了,现在用的人还很多吗? JSP 本身从 J2EE1.4(2003 年)到现在,快 15 年没更新了。

    差不多四五年前开始全部用 RESTful APIs + 前端 SPA 了。之前一段时间用模板技术比较多一些,freemarker, thymeleaf 都不错。

    Spring 分页 Controller method 同样可以接受 Pageable, 只需要加入 Pageable 就可以获取分页参数, 直接添加 page 到 Model 中,返回就完了,在页面都可能用 SPEL 读取。

    Spring Data 同样可以接受 Pageable, 返回 Page 就行了 。

    哪这么麻烦? 这哪一年的 Spring ?

    BaseController 的 getInstance, getRequest,ModelAndView 这种垃圾代码, 我真的醉了。

    早年使用 Struts 的人,对继承使用有切肤之痛,我早不再用这种无关紧要的继承。

    Logger 一般在当然类中声明为 static final 即可(想简单一点用 Lombok Annotation ),Request,ModelAndView 直接注入到方法就行了。

    findALL 注入了 Model, 又用 getModelAndView 来处理 Model ???@ResponseBody 和 produces="application/json" 是针对于 REST API 开发。而 ModelAndView 是为了处理传统 MVC。

    混成一团,我真怀疑有没有读过 Spring 参考文档啊??? 哪怕读一次也不可能写出这种代码。
    qinxi
        11
    qinxi  
       Dec 26, 2017
    @hantsy 这种人 b 了就是了,你看他从 8 月注册到现在除了推广 并没有任何互动。
    推广就算了。还是些垃圾代码。
    就是来骗小白的 star 的
    hantsy
        12
    hantsy  
       Dec 26, 2017
    @qinxi 关键现在很多人只喜欢 Copy 别人代码,根本不愿意动脑,或者去读原始参考文档,来甄别一些垃圾代码。B 掉了。
    xuminzhong
        13
    xuminzhong  
       Dec 26, 2017
    Java 写这种东西,冗余太多,不好看。
    建议别使用 Spring,直接返回 JSON。

    前端:html += "<tr><td><input type='checkbox' ...... 这种已经是上个世纪的写法了,非常难看。
    建议你了解下数据驱动的写法,比如 vue.js 是个入门好选择。
    xuminzhong
        14
    xuminzhong  
       Dec 26, 2017
    另外,Java Bean 写 Web 是一种浪费资源多余的做法,建议直接 Map。 ( public class User...)

    用接口写 Web 也是不推荐的,Java 有专门设计 Jsp tag 来处理这块东西,UserService、UserRepository 没必要存在。
    2gMvqdiq91WfMHOd
        15
    2gMvqdiq91WfMHOd  
       Dec 26, 2017
    我艹,我的代码基本上就和楼主的差不多,看了楼上几位大神的回复,我感觉这几年代码白写了....
    About     Help     Advertise     Blog     API     FAQ     Solana     3239 Online   Highest 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 58ms UTC 13:22 PVG 21:22 LAX 06:22 JFK 09:22
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86