分页
什么是分页
例:
第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;
}
}
/**
* 查询所有
* @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个,一个在出生时调用,一个在死亡时调用
void contextInitialized(ServletContextEvent sce):创建SErvletcontext时
void contextDestroyed(ServletContextEvent sce):销毁Servletcontext时
属性监听:ServletContextAttributeListener
方法:3个,一个在添加属性时调用,一个在替换属性时调用,最后一个是在移除属性时调用。
void attributeAdded(ServletContextAttributeEvent event):添加属性时;
void attributeReplaced(ServletContextAttributeEvent event):替换属性时
void attributeRemoved(ServletContextAttributeEvent event):移除属性时
HttpSession
生命周期监听:HttpSessionListener,
两个方法,一个在出生时调用,一个在死亡时调用
void sessionCreated(HttpSessionEvent se):创建session时
void sessionDestroyed(HttpSessionEvent se):销毁session时
属性监听:HttpSessioniAttributeListener,
三个方法,一个在添加属性时调用,一个在替换属性时调用,最后一个是在移除属性时调用。
void attributeAdded(HttpSessionBindingEvent event):添加属性时;
void attributeReplaced(HttpSessionBindingEvent event):替换属性时
void attributeRemoved(HttpSessionBindingEvent event):移除属性时
ServletRequest
生命周期监听:ServletRequestListener,
两个方法,一个在出生时调用,一个在死亡时调用;
void requestInitialized(ServletRequestEvent sre):创建request时
void requestDestroyed(ServletRequestEvent sre):销毁request时
属性监听:ServletRequestAttributeListener,
三个方法,一个在添加属性时调用,一个在替换属性时调用,最后一个是在移除属性时调用。
void attributeAdded(ServletRequestAttributeEvent srae):添加属性时
void attributeReplaced(ServletRequestAttributeEvent srae):替换属性时
void attributeRemoved(ServletRequestAttributeEvent srae):移除属性时
javaWeb中完成编写监听器:
1.写一个监听器类:要求必须去实现某个监听器接口;
2.注册,是在web.xml中配置来完成注册
事件对象及方法
ServletContextEvent:
ServletContext getServletContext()
HttpSessionEvent:
HttpSession getSession()
ServletRequest:
ServletContext getServletContext();
ServletReques getServletRequest();
ServletContextAttributeEvent:
ServletContext getServletContext();
String getName():获取属性名
Object getValue():获取属性值
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开始。