1.工具類
public final class QueryTool { public static PageRequest buildPageRequest(int pageNumber, int pageSize, String sortType){ Sort sort = null; if("auto".equals(sortType)) { sort = new Sort(Direction.DESC, "ctime"); } else { sort = new Sort(Direction.DESC, "ctime"); } return new PageRequest(pageNumber, pageSize, sort); } public static <T> Specification<T> buildSpecification(Map<String, Object> searchParams, Class<T> domainClass){ Map<String, SearchFilter> filters = SearchFilter.parse(searchParams); Specification<T> spec = DynamicSpecifications.bySearchFilter(filters.values(), domainClass); return spec; } }
2.Service類(只給出CommentService)
@Service public class CommentService { @Autowired private CommentDao commentDao; @Transactional public void addComment(Comment comment) { if(comment == null) return; commentDao.save(comment); } @Transactional public Page<Comment> findAllComments(String problemId, PageRequest pageable){ Page<Comment> page = commentDao.findAllCommentsByProblemId(problemId, pageable); return page; } }
3.repository類(problem 和 comment 屬於 一對多 的關系)
@Repository public interface CommentDao extends JpaSpecificationExecutor<Comment>, PagingAndSortingRepository<Comment, String> { @Query("select c from Comment c where c.problem.problemid = ?1") public Page<Comment> findAllCommentsByProblemId(String problemId, Pageable pageable); }
4.Controller類
第一種方式
@Controller public class ProblemController { @Autowired private ProblemService problemService; @Autowired private CommentService commentService; @RequestMapping(value="getCurProblemComments") @ResponseBody public String getCurProblemComments(String problemName, @RequestParam(value = "pn", defaultValue = "1") int pageNumber, @RequestParam(value = "ps", defaultValue = "4") int pageSize, @RequestParam(value = "sortType", defaultValue = "auto") String sortType){ JSONObject jsono = new JSONObject(); try { Problem problem = problemService.getProblemByName(problemName); if(problem == null){ problem = problemService.addProblem(problemName); } PageRequest pageRequest = QueryTool.buildPageRequest(pageNumber, pageSize, sortType); //根據題目的id獲取所有的評論 Page<Comment> page = commentService.findAllComments(problem.getProblemid(), pageRequest); //對 Comment 這個類中的一些字段進行過濾 SimplePropertyPreFilter spp = new SimplePropertyPreFilter(); spp.getExcludes().addAll(Comment.getExcludeString()); jsono.put("success", true); jsono.put("message", JSON.toJSONString(page, spp)); } catch(Exception e){ e.printStackTrace(); jsono.put("success", false); jsono.put("message", "inner error."); } return jsono.toString(); } }
第二種方式,(懶了,有些內容是放在servic中的。)
通過JpaSpecificationExecutor<T> 的Page<T> findAll(Specification<T> spec, Pageable pageable); 方法(按照指定的規格條件)實現分頁查詢。
public String getCurProblemComments(@RequestParam(value = "pn", defaultValue = "1") int pageNumber, @RequestParam(value = "ps", defaultValue = "2") int pageSize, @RequestParam(value = "sortType", defaultValue = "auto") String sortType, ServletRequest request) { Map<String, Object> searchParams = new HashMap<String, Object>(); searchParams = Servlets.getParametersStartingWith(request, "search_"); System.out.println(EncodeUtils.toUTF8((String)searchParams.get("LIKE_name"))); PageRequest pageRequest = QueryTool.buildPageRequest(pageNumber, pageSize, sortType); searchParams.put(Operator.EQ + "_dr", "0");//邏輯刪除中,字段dr=0表示這條數據沒有刪除 Specification<Comment> spec = QueryTool.buildSpecification(searchParams, Comment.class); Page<Comment> page = commentDao.findAll(spec, pageRequest); return JSON.toJSONString(page); }
其中,Specification中的一些比較操作org.springside.modules.persistence.SearchFilter.Operator這個類中找到,如下:
public static enum Operator { EQ, LIKE, GT, LT, GTE, LTE; }
前台傳遞過來的參數名稱中可以包含 Operator 中的一些操作, 比如參數名稱是: search_LIKE_name (search表示要查詢時比較, LIKE是比較的操作, name是表的字段名)。
5.java簡單實現分頁

分頁面板類(MyPagePanel.java)
public class MyPagePanel extends JPanel{ private final int PAGE_BTN_NUM = 6;//按鈕的數目的最大值, 一定為偶數 private JButton[] pageBtns = new JButton[PAGE_BTN_NUM]; private JButton preBtn = new JButton("<<");//前一頁 private JButton nextBtn = new JButton(">>");//后一頁 private JButton jumpBtn = new JButton("跳轉"); private JTextField jumpText = new JTextField(5);//輸入頁號 private JLabel totPageLabel = new JLabel("共0頁");//提示一共多少頁 public static final int PAGE_SIZE = 2; private CommunicationPanel parentPanel; private ChatPanel chatPanel; //刷新某頁 public void refreshPage(){ if(curPage == -1){ JOptionPane.showMessageDialog(null, "請選擇題目,然后再刷新!", "溫馨提示",JOptionPane.WARNING_MESSAGE); } else { requestPage(curPage); } } //請求某頁 public void requestPage(int pageNumber){ //當前頁按鈕設為 true if(curBtnPos >= 0) pageBtns[curBtnPos].setEnabled(true); JSONObject jsono = new JSONObject(); jsono.put("problemName", JavaRequest.problemName); jsono.put("pageSize", String.valueOf(PAGE_SIZE)); jsono.put("pageNumber", String.valueOf(pageNumber)); String data = JavaRequest.sendPost("getCurProblemComments", jsono); //獲取當前題目的 評論記錄 JSONObject result = JSONObject.fromObject(data); if((Boolean) result.get("success")){//分頁顯示 JSONObject message = JSONObject.fromObject(result.get("message")); Map<String, Class<?>> classMap = new HashMap<String, Class<?>>(); classMap.put("content", MyMessage.class); MyPage myPage = (MyPage) JSONObject.toBean(message, MyPage.class, classMap); this.updatePage(myPage); } else { JOptionPane.showMessageDialog(null, result.getString("message"), "溫馨提示",JOptionPane.WARNING_MESSAGE); if(result.get("returnLogin") != null && (Boolean)result.get("returnLogin")){//如果用戶登錄超時返回用戶登陸界面 parentPanel.switchPanel(CommunicationPanel.LOGIN_PANEL); } } } //跳轉都頁面 private void jumpPage(int pageNumber) throws Exception{ if(pageNumber < 0 || pageNumber >= totalPages) throw new Exception("不存在該頁號!"); requestPage(pageNumber); } public MyPagePanel(CommunicationPanel parentPanelx, ChatPanel chatPanelx){ this.parentPanel = parentPanelx; this.chatPanel = chatPanelx; preBtn.setEnabled(false); this.add(preBtn); preBtn.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { requestPage(curPage-1); } }); for(int i=0; i<pageBtns.length; ++i) { pageBtns[i] = new JButton(); this.add(pageBtns[i]); pageBtns[i].setVisible(false); pageBtns[i].addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { //JButton text 表示的是頁號 String text = ((JButton)e.getSource()).getText(); int pageNumber = Integer.valueOf(text); requestPage(pageNumber); } }); } nextBtn.setEnabled(false); this.add(nextBtn); nextBtn.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { requestPage(curPage+1); } }); jumpBtn.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { try{ if(jumpText.getText().isEmpty()) throw new Exception("頁數不能為空!"); int pageNumber = Integer.valueOf(jumpText.getText()); jumpPage(pageNumber); } catch (Exception ex){ ex.printStackTrace(); JOptionPane.showMessageDialog(null, "請確定頁號是否正確!", "溫馨提示",JOptionPane.WARNING_MESSAGE); } } }); this.add(totPageLabel); this.add(jumpText); this.add(jumpBtn); } private int curPage = -1, totalPages, curBtnPos = -1; public void updatePage(MyPage myPage){ //清除當頁面的信息 chatPanel.getJpChat().setText(""); //處理接受到的 評論消息 for(MyMessage message : myPage.getContent()){ chatPanel.addRecMsg(message.getCcontent(), StyleConstants.ALIGN_LEFT); } curPage = myPage.getNumber(); totalPages = myPage.getTotalPages(); totPageLabel.setText("共" + totalPages + "頁"); if(curPage == 0) preBtn.setEnabled(false); else preBtn.setEnabled(true); if(curPage == totalPages-1 || totalPages == 0) nextBtn.setEnabled(false); else nextBtn.setEnabled(true); List<Integer> pageNum = new LinkedList<Integer>(); if(totalPages > 0) { int step = PAGE_BTN_NUM/2-1; for(int i=step; i>=1; --i) { if(curPage-i>=0) pageNum.add(curPage-i); } pageNum.add(curPage); for(int i=1; i<=step+1 && curPage+i<totalPages; ++i) pageNum.add(curPage+i); if(pageNum.size() < PAGE_BTN_NUM){ while(pageNum.size() < PAGE_BTN_NUM && pageNum.get(0)-1 >= 0) pageNum.add(0, pageNum.get(0)-1); while(pageNum.size() < PAGE_BTN_NUM && pageNum.get(pageNum.size()-1)+1 < totalPages) pageNum.add(pageNum.get(pageNum.size()-1)+1); } } int bi = 0; for(int pi=0; pi < pageNum.size(); ++pi, ++bi){ pageBtns[bi].setText(String.valueOf(pageNum.get(pi))); if(pageNum.get(pi) == curPage){ curBtnPos = bi;//記錄這個按鈕的頁號值 和 當前頁號值相等 } } //重新顯示按鈕 for(int i=0; i<bi; ++i) pageBtns[i].setVisible(true); //后面這些按鈕都是沒有 用上的 for(int i=bi; i < pageBtns.length; ++i){ pageBtns[i].setVisible(false); } if(totalPages > 0) pageBtns[curBtnPos].setEnabled(false); } }
MyMessage.class
public class MyMessage{ private String ccontent; private String commentid; public String getCcontent() { return ccontent; } public void setCcontent(String ccontent) { this.ccontent = ccontent; } public String getCommentid() { return commentid; } public void setCommentid(String commentid) { this.commentid = commentid; } }
MyPage.class
public class MyPage{ private List<MyMessage> content; private boolean first; private boolean last; private int number; private int numberOfElements; private int size; private String totalElements; private String sort; public String getSort() { return sort; } public void setSort(String sort) { this.sort = sort; } public List<MyMessage> getContent() { return content; } public void setContent(List<MyMessage> content) { this.content = content; } public boolean isFirst() { return first; } public void setFirst(boolean first) { this.first = first; } public boolean isLast() { return last; } public void setLast(boolean last) { this.last = last; } public int getNumber() { return number; } public void setNumber(int number) { this.number = number; } public int getNumberOfElements() { return numberOfElements; } public void setNumberOfElements(int numberOfElements) { this.numberOfElements = numberOfElements; } public int getSize() { return size; } public void setSize(int size) { this.size = size; } public String getTotalElements() { return totalElements; } public void setTotalElements(String totalElements) { this.totalElements = totalElements; } public int getTotalPages() { return totalPages; } public void setTotalPages(int totalPages) { this.totalPages = totalPages; } private int totalPages; }
實現思路:
1. 首先看一下后台的json數據的格式(其中message的值是spring Data JPA分頁查詢結果的json)
{"success":true,"message":{"content":[{"ccontent":"hjz 2016-38-11 15:38:21*****宋體|12|0-0-0| *****0$$$$$70#####","commentid":"8ae45d92549da2a801549ec092ce001f"},{"ccontent":"hjz 2016-38-11 15:38:10*****宋體|12|0-0-0|哇哇 *****2$$$$$55#####","commentid":"8ae45d92549da2a801549ec068c7001e"}],"first":true,"last":false,"number":0,"numberOfElements":2,"size":2,"sort":{},"totalElements":8,"totalPages":4}}
2. 將“message”對應的值轉換成MyPage對象,因為MyPage中有一個List<MyMessage>,如果屬性中含有復雜的類型,當其中屬性有類似List , Map ,ArrayList、自定義的類型,如List<MyMessage> content, 普通的轉換會報錯:java.lang.ClassCastException: net.sf.ezmorph.bean.MorphDynaBean cannot be cast to XXX,在JSONObject.toBean的時候如果轉換的類中有集合,可以先定義Map<String, Class> classMap = new HashMap<String, Class>();在classMap中put你要轉換的類中的集合名 。本例中需要將“content”對應的值轉換成 MyMessage對象。
//data為后台的json串 JSONObject result = JSONObject.fromObject(data); if((Boolean) result.get("success")){//分頁顯示 JSONObject message = JSONObject.fromObject(result.get("message")); Map<String, Class<?>> classMap = new HashMap<String, Class<?>>(); classMap.put("content", MyMessage.class); MyPage myPage = (MyPage) JSONObject.toBean(message, MyPage.class, classMap); this.updatePage(myPage); }
3.然后通過分頁的信息,簡單的實現分頁按鈕,詳情看MyPagePanel.java
