分页
什么是分页
例:
第N页/共M页 首页 上一页 1 2 3 4 5 6 7 8 9 10 下一页 尾页 口 go
分页的优点:只查询一页,不用查询所有页
分页数据
页面的数据都是由Servlet传递来的
Servlet:
1.当前页面页数:pageCode,pc(没有传递按默认第一页)
2.总页数:totalPages,tp(总记录数/每页记录数)
3.总记录数:totalRecored,tr(dao来获取,select count(*) fromt_customer)\
4.每页记录数:pageSize,ps
5.当前页的记录:beanList
6.url:保存/项目名,保存/Servlet路径,保存?后面的参数(既保留多条件查询的条件)
分页Bean的设计
页数据总要在各层之间来回的传递,这些分页数据封装到一个javabean中,
它就叫分页Bean,例如:PageBean
代码
public class PageBean<T> { private int pc;// 当前页码page code // private int tp;// 总页数total page private int tr;// 总记录数total record private int ps;// 每页记录数page size private List<T> beanList;// 当前页的记录 private String url;//它就是url后的条件! public String getUrl() { return url; } public void setUrl(String url) { this.url = url; } public int getPc() { return pc; } public void setPc(int pc) { this.pc = pc; } /** * 计算总页数 * @return */ public int getTp() { // 通过总记录数和每页记录数来计算总页数 int tp = tr / ps; return tr%ps==0 ? tp : tp+1; } // public void setTp(int tp) { // this.tp = tp; // } public int getTr() { return tr; } public void setTr(int tr) { this.tr = tr; } public int getPs() { return ps; } public void setPs(int ps) { this.ps = ps; } public List<T> getBeanList() { return beanList; } public void setBeanList(List<T> beanList) { this.beanList = beanList; } }
分页在各层中的处理
Servlet传递pc,设定ps
由dao层返回一个PageBean
保存到域中再由页面显示
图
图2
显示分页页码列表
1 2 3 4 5 [6] 7 8 9 10
↑最多显示多少个页码!定为10
↑当前页,在页码列表中的位置,定为6
↑只需要当前页码来定出来页码列表
↓定下来页码列表只需要两样数据
1.begin
2.end
10 11 12 13 14 [15] 16 17 18 19
需要使用pc来推算出begin和end
begin = pc – 5
end = pc + 4
公式:
*如果总页数<=10(列表长度),那么begin=1,end=总页数
*使用公式计算;begin=pc-5, end=pc + 4
*头溢出:当begin<1时,让begin=1
*尾溢出:当end>${tp}时,让end=${tp}
代码
... JSP <%-- 给出分页的链接 --%> <center> 第${pb.pc }页/共${pb.tp }页 <a href="${pb.url }&pc=1">首页</a> <c:if test="${pb.pc > 1 }"> <a href="${pb.url }&pc=${pb.pc-1}">上一页</a> </c:if> <%-- 计算begin、end --%> <c:choose> <%-- 如果总页数不足10页,那么把所有的页数都显示出来! --%> <c:when test="${pb.tp <= 10 }"> <c:set var="begin" value="1" /> <c:set var="end" value="${pb.tp }" /> </c:when> <c:otherwise> <%-- 当总页数>10时,通过公式计算出begin和end --%> <c:set var="begin" value="${pb.pc-5 }" /> <c:set var="end" value="${pb.pc+4 }" /> <%-- 头溢出 --%> <c:if test="${begin < 1 }"> <c:set var="begin" value="1" /> <c:set var="end" value="10" /> </c:if> <%-- 尾溢出 --%> <c:if test="${end > pb.tp }"> <c:set var="begin" value="${pb.tp - 9 }" /> <c:set var="end" value="${pb.tp }" /> </c:if> </c:otherwise> </c:choose> <%-- 循环遍历页码列表 --%> <c:forEach var="i" begin="${begin }" end="${end }"> <c:choose> <c:when test="${i eq pb.pc }"> [${i }] </c:when> <c:otherwise> <a href="${pb.url }&pc=${i}">[${i }]</a> </c:otherwise> </c:choose> </c:forEach> <c:if test="${pb.pc < pb.tp }"> <a href="${pb.url }&pc=${pb.pc+1}">下一页</a> </c:if> <a href="${pb.url }&pc=${pb.tp}">尾页</a> </center> </body> </html>
在超链接中要保留参数
当使用多条件查询后,然后在点击第2 页时,这个第2页超链接没有条件了,
所以会丢失条件,所以我们需要在页面上的所有链接都要保留条件
要把条件以一个字符串的形式保存到PageBean的url中!这个任务交给Servlet
代码
web层相关
public String findAll(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { /* * 1. 获取页面传递的pc * 2. 给定ps的值 * 3. 使用pc和ps调用service方法,得到PageBean,保存到request域 * 4. 转发到list.jsp */ int pc = getPc(request);//得到pc int ps = 10;//给定ps的值,第页10行记录 PageBean<Customer> pb = customerService.findAll(pc, ps);//传递pc, ps给Service,得到PageBean // 设置url pb.setUrl(getUrl(request)); request.setAttribute("pb", pb);//保存到request域中 return "f:/list.jsp";//转发到list.jsp } /** * 获取pc * @param request * @return */ private int getPc(HttpServletRequest request) { /* * 1. 得到pc * 如果pc参数不存在,说明pc=1 * 如果pc参数存在,需要转换成int类型即可 */ String value = request.getParameter("pc"); if(value == null || value.trim().isEmpty()) { return 1; } return Integer.parseInt(value); } public String query(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // System.out.println(getUrl(request)); /* * 0. 把条件封装到Customer对象中 * 1. 得到pc * 2. 给定ps * 3. 使用pc和ps,以及条件对象,调用service方法得到PageBean * 4. 把PageBean保存到request域中 * 5. 转发到list.jsp */ // 获取查询条件 Customer criteria = CommonUtils.toBean(request.getParameterMap(), Customer.class); /* * 处理GET请求方式编码问题! */ criteria = encoding(criteria); int pc = getPc(request);//得到pc int ps = 10;//给定ps的值,第页10行记录 PageBean<Customer> pb = customerService.query(criteria, pc, ps); // 得到url,保存到pb中 pb.setUrl(getUrl(request)); request.setAttribute("pb", pb); return "f:/list.jsp"; } /** * 处理四样 * @param criteria * @return * @throws UnsupportedEncodingException */ private Customer encoding(Customer criteria) throws UnsupportedEncodingException { String cname = criteria.getCname(); String gender = criteria.getGender(); String cellphone = criteria.getCellphone(); String email = criteria.getEmail(); if(cname != null && !cname.trim().isEmpty()) { cname = new String(cname.getBytes("ISO-8859-1"), "utf-8"); criteria.setCname(cname); } if(gender != null && !gender.trim().isEmpty()) { gender = new String(gender.getBytes("ISO-8859-1"), "utf-8"); criteria.setGender(gender); } if(cellphone != null && !cellphone.trim().isEmpty()) { cellphone = new String(cellphone.getBytes("ISO-8859-1"), "utf-8"); criteria.setCellphone(cellphone); } if(email != null && !email.trim().isEmpty()) { email = new String(email.getBytes("ISO-8859-1"), "utf-8"); criteria.setEmail(email); } return criteria; } /** * 截取url * /项目名/Servlet路径?参数字符串 * @param request * @return */ private String getUrl(HttpServletRequest request) { String contextPath = request.getContextPath();//获取项目名 String servletPath = request.getServletPath();//获取servletPath,即/CustomerServlet String queryString = request.getQueryString();//获取问号之后的参数部份 // 判断参数部份中是否包含pc这个参数,如果包含,需要截取下去,不要这一部份。 if(queryString.contains("&pc=")) { int index = queryString.lastIndexOf("&pc="); queryString = queryString.substring(0, index); } return contextPath + servletPath + "?" + queryString; } }
dao层相关
/** * 查询所有 * @return */ public PageBean<Customer> findAll(int pc, int ps) { try { /* * 1. 他都PageBean对象pb * 2. 设置pb的pc和ps * 3. 得到tr,设置给pb * 4. 得到beanList,设置给pb * 5. 返回pb */ PageBean<Customer> pb = new PageBean<Customer>(); pb.setPc(pc); pb.setPs(ps); /* * 得到tr */ String sql = "select count(*) from t_customer"; Number num = (Number)qr.query(sql, new ScalarHandler()); int tr = num.intValue(); pb.setTr(tr); /* * 得到beanList */ sql = "select * from t_customer order by cname limit ?,?"; List<Customer> beanList = qr.query(sql, new BeanListHandler<Customer>(Customer.class), (pc-1)*ps, ps); pb.setBeanList(beanList); return pb; } catch(SQLException e) { throw new RuntimeException(e); } } //多条件查询 带分页 public PageBean<Customer> query(Customer criteria, int pc, int ps) { try { /* * 1. 创建PageBean对象 * 2. 设置已有的属性,pc和ps * 3. 得到tr * 4. 得到beanList */ /* * 创建pb,设置已有属性 */ PageBean<Customer> pb = new PageBean<Customer>(); pb.setPc(pc); pb.setPs(ps); /* * 得到tr */ /* * 1. 给出一个sql语句前半部 */ StringBuilder cntSql = new StringBuilder("select count(*) from t_customer"); StringBuilder whereSql = new StringBuilder(" where 1=1"); /* * 2. 判断条件,完成向sql中追加where子句 */ /* * 3. 创建一个ArrayList,用来装载参数值 */ List<Object> params = new ArrayList<Object>(); String cname = criteria.getCname(); if(cname != null && !cname.trim().isEmpty()) { whereSql.append(" and cname like ?"); params.add("%" + cname + "%"); } String gender = criteria.getGender(); if(gender != null && !gender.trim().isEmpty()) { whereSql.append(" and gender=?"); params.add(gender); } String cellphone = criteria.getCellphone(); if(cellphone != null && !cellphone.trim().isEmpty()) { whereSql.append(" and cellphone like ?"); params.add("%" + cellphone + "%"); } String email = criteria.getEmail(); if(email != null && !email.trim().isEmpty()) { whereSql.append(" and email like ?"); params.add("%" + email + "%"); } /* * select count(*) .. + where子句 * 执行之 */ Number num = (Number)qr.query(cntSql.append(whereSql).toString(), new ScalarHandler(), params.toArray()); int tr = num.intValue(); pb.setTr(tr); /* * 得到beanList */ StringBuilder sql = new StringBuilder("select * from t_customer"); // 我们查询beanList这一步,还需要给出limit子句 StringBuilder limitSql = new StringBuilder(" limit ?,?"); // params中需要给出limit后两个问号对应的值 params.add((pc-1)*ps); params.add(ps); // 执行之 List<Customer> beanList = qr.query(sql.append(whereSql).append(limitSql).toString(), new BeanListHandler<Customer>(Customer.class), params.toArray()); pb.setBeanList(beanList); return pb; } catch(SQLException e) { throw new RuntimeException(e); } } }
JavaWeb监听器
三大组件:Servlet/Listener/Filter
Listener:监听器
1.初次相见:AWT
2.二次相见:SAX
监听器:
它是一个接口,内容由我们来实现
它需要注册,例如注册在按钮上
监听器中的方法,会在特殊事件发生时被调用
观察者:
例:
事件源:小偷
事件:偷东西
监听器:警察
监听器中的方法:抓捕
JavaWeb中的监听器
事件源:三大域-ServletContext/HttpSession/ServletRequest
ServletContext
生命周期监听:ServletContextListener
方法:2个,一个在出生时调用,一个在死亡时调用
voidcontextInitialized(ServletContextEvent sce):创建SErvletcontext时
voidcontextDestroyed(ServletContextEvent sce):销毁Servletcontext时
属性监听:ServletContextAttributeListener
方法:3个,一个在添加属性时调用,一个在替换属性时调用,最后一个是在移除属性时调用。
voidattributeAdded(ServletContextAttributeEvent event):添加属性时;
voidattributeReplaced(ServletContextAttributeEvent event):替换属性时
voidattributeRemoved(ServletContextAttributeEvent event):移除属性时
HttpSession
生命周期监听:HttpSessionListener,
两个方法,一个在出生时调用,一个在死亡时调用
voidsessionCreated(HttpSessionEvent se):创建session时
voidsessionDestroyed(HttpSessionEvent se):销毁session时
属性监听:HttpSessioniAttributeListener,
三个方法,一个在添加属性时调用,一个在替换属性时调用,最后一个是在移除属性时调用。
voidattributeAdded(HttpSessionBindingEvent event):添加属性时;
voidattributeReplaced(HttpSessionBindingEvent event):替换属性时
voidattributeRemoved(HttpSessionBindingEvent event):移除属性时
ServletRequest
生命周期监听:ServletRequestListener,
两个方法,一个在出生时调用,一个在死亡时调用;
voidrequestInitialized(ServletRequestEvent sre):创建request时
voidrequestDestroyed(ServletRequestEvent sre):销毁request时
属性监听:ServletRequestAttributeListener,
三个方法,一个在添加属性时调用,一个在替换属性时调用,最后一个是在移除属性时调用。
voidattributeAdded(ServletRequestAttributeEvent srae):添加属性时
voidattributeReplaced(ServletRequestAttributeEvent srae):替换属性时
voidattributeRemoved(ServletRequestAttributeEvent srae):移除属性时
javaWeb中完成编写监听器:
1.写一个监听器类:要求必须去实现某个监听器接口;
2.注册,是在web.xml中配置来完成注册
事件对象及方法
ServletContextEvent:
ServletContextgetServletContext()
HttpSessionEvent:
HttpSessiongetSession()
ServletRequest:
ServletContextgetServletContext();
ServletRequesgetServletRequest();
ServletContextAttributeEvent:
ServletContextgetServletContext();
StringgetName():获取属性名
ObjectgetValue():获取属性值
HttpSessionBindingEvent:同上/获取相应对象/属性名/属性值
ServletRequestAttributeEvent :同上/获取相应对象/属性名/属性值
感知监听(都与HttpSession相关)
区别:
它用来添加到JavaBean上,而不是添加到三大域上!
这两个监听器都不需要在web.xml中注册
HttpSessionBindingListener:添加到javabean上,javabean就知道自己是否添加到session中了。
HttpSessionActivationListener:Tomcat钝化/活化session时→保存到硬盘/从硬盘加载到内存,javabean可以感知到相关操作
钝化和活化
其实就是使用序列化和反序列化技术把session从内存保存到硬盘,和把session从硬盘加载到内存
如果javabean没有实现Serializable(序列化)接口,当session钝化时就不会钝化,
而是把Person从session中移除再钝化!这也说明session活化后,session中就不在有javabean对象了
国际化
什么是国际化:国际化就是可以把页面中的中文变成英文。
理解国际化:想把页面文字修改就不能硬编码 ,而是把相应文字编成变量
Locale类
newLocale(“zh”, “CN”);
newLocale(“en”, “US”);
一个Locale对象表示的就是语言和国家
ResourceBundle类
ReourceBundle类用来获取配置文件中的内容
ResourceBundle的getBundle()方法需要两个参数:
1.配置文件的基本名称
2.Locale
getBundle()方法会通过两个参数来锁定配置文件
页面国际化
图
NumberFormat
NumberFormat类用来对数字进行格式化:需要使用Stringformat(double)方法
DateFormat
DateFormat类用来对日期进行格式化:需要使用Stringformat(Date)方法
MessageFormat
MessageFormat可以把模式中的{N}使用参数来替换。我们把{N}称之为点位符。其中点位符中的N是从0开始的整数。
MessageFormat.format(String pattern, Object… params),其中pattern中可以包含0~n个点位符,而params表示对点位符的替换文本。注意,点位符需要从0开始。