自定义mvc复习2

自定义MVC

  • 1、反射
    • 1.1反射是什么
    • 1.2反射怎么用
    • 1.3反射运用举例
  • 2、通用分页中用到的自定义标签
    • 2.1自定义标签的生命周期
    • 2.2为什么我们要掌握自定义标签
    • 2.3标签语言特点
    • 2.4自定义标签的开发及使用步骤
  • 3、通用分页
  • 总结

1、反射

1.1反射是什么

反射是所有框架的基础,是java语言的一种机制,通过反射可以动态的实例化对象,读写属性,调用方法,更加灵活。

1.2反射怎么用

一般可以用在一些通用工具类的封装和自定义框架
一切反射相关的代码都从获得类对象开始
获得类对象有三种方法
1.Class.forName(完整的类名)
2.类名.class
3.对象.getClass()

1.3反射运用举例

1、像我们平常连接数据库加载驱动时就会用到:
Class.forName(cname);
2、实例化时
JobDao jd=Class.forName(com.wangjuanxia.dao.JobAction).newInstance();

2、通用分页中用到的自定义标签

解析:通用分页就是就是把分页方法的共同代码封装起来,利用泛型去传递类对象,然后利用反射获取对象属性给对象属性赋值,这样在之后的项目中就可以直接用了,节省代码,更加方便。

2.1自定义标签的生命周期

这里我画了一个图,可看图理解:

自定义mvc复习2_第1张图片

2.2为什么我们要掌握自定义标签

为了更加灵活的完成开发需求,通俗点说就是可以自己去定义我开发时需要的功能的标签

2.3标签语言特点

<开始标签>标签体
// 例如:文字标签
<span>123</span>
空标签,空标签就没有标签体
// 例如:换行
<br/>

2.4自定义标签的开发及使用步骤

1、创建一个标签助手类,要继承BodyTagSupport,标签属性必须和助手类的属性对应,
且要提供对应的get,set方法。(这里拿下面通用分页要用到的page标签做例)
public class PageTag extends BodyTagSupport{

	private static final long serialVersionUID = 1L;
	private PageBean pageBean;
	//封装
	public PageBean getPageBean() {
		return pageBean;
	}
	public void setPageBean(PageBean pageBean) {
		this.pageBean = pageBean;
	}
	
	@Override
	public int doStartTag() throws JspException {
		// TODO Auto-generated method stub
		try {
			JspWriter out=this.pageContext.getOut();
			out.println(toHtml());
			return SKIP_BODY;
		} catch (Exception e) {
			// TODO: handle exception
			throw new RuntimeException(e);
		}
	}
	
	
	private String toHtml() {
		// TODO Auto-generated method stub
		StringBuffer sb=new StringBuffer();
		//防止pageBean空指针异常
		if(null==pageBean||!pageBean.isPagination()) {
			return sb.toString();
		}
		
		//这里拼接分页按钮
		sb.append("
\r\n" + " 当前第"+pageBean.getPage()+"页  共"+pageBean.getMaxPage()+"页  共"+pageBean.getTotal()+"条  \r\n" + " 首页  \r\n" + " 上一页  \r\n" + " 下一页  \r\n" + " 尾页  \r\n" + " \r\n" + " GO\r\n" + "
"
); //分页隐藏域表单 专门用来传递数据 sb.append("
"); sb.append(""); //从map集合中获取参数 Map<String, String[]> parameterMap=pageBean.getParameterMap(); //遍历集合 for (Map.Entry<String, String[]> entry : parameterMap.entrySet()) { String name=entry.getKey(); String[] value=entry.getValue(); if("page".equals(name)) {//将上一次的页码抛掉 continue;//退出当前循环,进入下一个循环 } //遍历数组 for (int i = 0; i < value.length; i++) { sb.append(""); } } sb.append(""
); //这里动态拼接js sb.append(" "); return sb.toString(); } }
2、创建标签库描述文件(.tld),添加自定义标签的配置

注意:.tld文件必须保存到WEB-INF目录或其子目录下

<!DOCTYPE taglib
  PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN"
   "http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd">
<!-- 标签库描述符 -->
<taglib xmlns="http://java.sun.com/JSP/TagLibraryDescriptor">
	<tlib-version>1.0</tlib-version>
	<jsp-version>1.2</jsp-version>
	<short-name>Simple Tags</short-name>
	<!-- 这里放jsp界面taglib命令调用的路径 -->
	<uri>/wangjuanxia</uri>
	<tag>
		<!-- 标签名 -->
		<name>page</name>
		<!-- 标签助手类 -->
		<tag-class>com.solar.tag.PageTag</tag-class>
		<!-- 标签的内容类型:empty表示空标签,jsp表示可以为任何合法的JSP元素 -->
		<body-content>empty</body-content>
		<!-- 自定义标签的属性定义,请注意一定要在标签类中提供对应的get/set方法 -->
		<attribute>
			<!-- 自定义标签的属性名称 -->
			<name>pageBean</name>
			<!-- true表示必填 -->
			<required>true</required>
			<!-- true支持动态值,可以向值里面填jsp表达式、EL表达式,false则不支持 -->
			<rtexprvalue>true</rtexprvalue>
			<description></description><!-- 属性的描述,可有可无,要放在属性的最后 -->
		</attribute>
	</tag>
</taglib>
3、在JSP通过taglib指令导入标签描述文件,并通过指定后缀访问自定义标签

通过taglib指令导入

<%@taglib prefix="z" uri="/wangjuanxia" %>

访问

<z:page pageBean="${pageBean }"/>

3、通用分页

最后效果
在这里插入图片描述
1、连接数据库,最基本的操作这里就不细讲了(调用分页我用的mysql的数据库)
导jar包
在这里插入图片描述
2、定义工具类pageBean,来控制是否分页,页数,每页数量

/**
 * 分页工具类
 */
public class PageBean {

	private int page = 1;// 页码
	private int rows = 10;// 页大小
	private int total = 0;// 总记录数,从数据库中统计的
	
	private boolean pagination = true;// 是否分页 默认分页

	private String url;
	private Map<String, String[]> ParameterMap = new HashMap<String, String[]>();
	 
	
	
	
	
	//专门写一个方法,做pageBean的初始化
    public void setRequest(HttpServletRequest request) {
    	System.out.println("pagebean初始化");
		String page= request.getParameter("page");
		String rows= request.getParameter("rows");
		String pagination = request.getParameter("pagination");
		
		this.setPage(page);
		this.setRows(rows);
		this.setPagination(pagination);
		
		this.url=request.getContextPath()+request.getServletPath();
		 
		this.ParameterMap =request.getParameterMap();
		 
	 }
    
    //上一页
	public int getPreviousPage() {
		System.out.println("getPreviousPage");
		int previousPage=this.page-1;
		if(0==previousPage) {
			previousPage=1;
		}
		return previousPage;
	}
	
	//下一页
	public int getNextPage() {
		System.out.println("getNextPage");
		int nextPage=this.page+1;
		if(nextPage>getMaxPage()) {//大于最大页
			nextPage=getMaxPage();
		}
		return nextPage;
	}

	public int getPage() {
		return page;
	}

	public void setPage(int page) {
		this.page = page;
	}
	public void setPage(String page) {
		if(null!=page &&!"".equals(page.trim())){
			this.page =Integer.parseInt(page);
		}
	}

	public Map<String, String[]> getParameterMap() {
		return ParameterMap;
	}

	public void setParameterMap(Map<String, String[]> parameterMap) {
		ParameterMap = parameterMap;
	}

	public String getUrl() {
		return url;
	}

	public void setUrl(String url) {
		this.url = url;
	}

	public int getRows() {
		return rows;
	}

	public void setRows(int rows) {
		this.rows = rows;
	}
	public void setRows(String rows) {
		if(null!=rows &&!"".equals(rows.trim())){
			this.rows =Integer.parseInt(rows);
		}
	}

	public int getTotal() {
		return total;
	}

	public void setTotal(int total) {
		this.total = total;
	}

	public void setTotal(String total) {
		this.total = Integer.parseInt(total);
	}

	public boolean isPagination() {
		return pagination;
	}

	public void setPagination(boolean pagination) {
		this.pagination = pagination;
	}
	public void setPagination(String pagination) {
		if("false".equals(pagination)) {
			this.pagination = Boolean.parseBoolean(pagination);
		}
	}
	
	
	public PageBean() {
		super();
	}
	
	/**
	 * 获得起始记录的下标
	 * 
	 * @return
	 */
	public int getStartIndex() {
		return (this.page-1)*this.rows;
		
	}
	
	/**
	 * 获取最大页数
	 * @return
	 */
	public int getMaxPage() {
		int maxPage=this.total/this.rows;
		if(0!=this.total%this.rows) {
			maxPage++;
		}
		return maxPage;
	}
	
	

	@Override
	public String toString() {
		return "PageBean [page=" + page + ", rows=" + rows + ", total=" + total + ", pagination=" + pagination + "]";
	}

}

3、实体类(字段,封装,构造方法)
在这里插入图片描述
4、工具类
从上至下,依次为(连接数据库工具类、字符编码过滤工具类、分页工具类、连接各种数据库配置工具类)在这里插入图片描述
5、将一般增删改查重复的部分写一个泛型,专门写一个方法用来拼接查询语句的统计满足条件的总行数,专门写一个方法用来存储拼接分页的sql,再在里面写一个内部类将不同的遍历部分放进去,解决每个表字段不一样的问题。

//SOLAR
public class BaseDao<k> {
	public interface Callback<k>{
		public List<k> foreach(ResultSet rs) throws SQLException;
	}
	public String getCountSql(String sql) {
		return "select count(*) from ("+sql+") t1";
	}
	public String getPageSql(String sql,PageBean pageBean) {
		return sql+"limit "+pageBean.getStartIndex()+","+pageBean.getRows()+"";
	}
	public List<k> executeQuery(String sql,PageBean pageBean,Callback<k> callback){
		
		Connection con=null;
		PreparedStatement ps=null;
		ResultSet rs=null;
		if(null!=pageBean&&pageBean.isPagination()) {
		//1、统计满足条件的总行数
		try {
			con=DBAccess.getConnection();
			String countSql=this.getCountSql(sql);
			ps=con.prepareStatement(countSql);
			rs=ps.executeQuery();
			if(rs.next()) {
				int total=rs.getInt(1);
				pageBean.setTotal(total);
			}
		} catch (Exception e) {
			// TODO: handle exception
			throw new RuntimeException(e);
		}finally {
			DBAccess.close(null, ps, rs);//不能把连接关闭
		}
		}
		//2、查询指定页码并满足条件的总记录数
		try {
			if(con==null) {
				con=DBAccess.getConnection();
			}
			String pageSql=sql;
			if(null!=pageBean&&pageBean.isPagination()) {
				
				pageSql=getPageSql(sql, pageBean);
			}
			ps=con.prepareStatement(pageSql);
			rs=ps.executeQuery();
			return callback.foreach(rs);
			} catch (Exception e) {
				// TODO: handle exception
				throw new RuntimeException(e);
			}finally {
				DBAccess.close(con, ps, rs);
			}
	}

}

5.在dao类里继承第4步里创建的BaseDao,重写executeQuery方法,遍历存储取出来的字段,返回结果集

public List<Job> find(PageBean pageBean){
		String sql="select * from t_solr_job where 1=1 ";
		return this.executeQuery(sql, pageBean, new Callback<Job>() {

			@Override
			public List<Job> foreach(ResultSet rs) throws SQLException {
				List<Job> jobList = new ArrayList<Job>();
				Job j = null;
				while(rs.next()) {
					j = new Job();
					j.setId(rs.getString("id"));
					j.setJob(rs.getString("job"));
					j.setCompany(rs.getString("company"));
					j.setAddress(rs.getString("address"));
					j.setSalary(rs.getString("salary"));
					j.setUrl(rs.getString("url"));
					j.setLimit(rs.getString("limit"));
					j.setTime(rs.getString("time"));
					j.setDesc(rs.getString("desc"));
					j.setJobHandle(rs.getString("jobHandle"));
					j.setAddressHandle(rs.getString("addressHandle"));
					jobList.add(j);				
				}							
				return jobList;
			}
		});
	
}

6、写servlet,继承HttpServlet,写两个方法(doget,dopost),实例化分页工具类,调用方法

public class JobServlet extends HttpServlet{

	private static final long serialVersionUID = 1L;
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
	// TODO Auto-generated method stub
	doPost(req, resp);
}
@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		// TODO Auto-generated method stub
		//设置字符编码
			req.setCharacterEncoding("utf-8");
			resp.setContentType("text/html;charset=utf-8");
			//实例化dao方法
			JobDao  jd = new JobDao();
			//实例化分页工具类,调用方法
			PageBean pageBean = new PageBean();
			pageBean.setRequest(req);
			req.setAttribute("pageBean", pageBean);
			//调用分页方法
			List<Job> joblist= jd.find(pageBean);
			//存储
			req.setAttribute("joblist", joblist);
			//跳转界面
			req.getRequestDispatcher("index.jsp").forward(req, resp);
	}
}

7.jsp界面

<%@ page language="java" contentType="text/html; charset=utf-8"
    pageEncoding="utf-8"%>
    <!-- taglib指令导入标签描述文件 -->
    <%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
	<%@taglib prefix="z" uri="/wangjuanxia" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Insert title here</title>

</head>
<body>
	 <!-- 判断结果集是否有值 -->
 	<c:if test="${empty joblist }">
 		<jsp:forward page="jobServlet.action"></jsp:forward>
 	</c:if>
 	<table border="1px" width="100%"> 
 		<tr>
 		
 		 	<td>id</td>
 		 	<td>job</td>
 		 	<td>company</td>
 		 	<td>address</td>
 		 	<td>salary</td>
 		 	<td>url</td>
 		 	<td>limit</td>
 		 	<td>time</td>
 		 	<td>desc</td>
 		 	<td>jobHandle</td>
 		 	<td>addressHandle</td>
 		</tr>
 		 <!-- 遍历 -->
 		<c:forEach items="${joblist}" var="j" >
 		<tr>
 		 	<td>${j.id }</td>
 		 	<td>${j.job }</td>
 		 	<td>${j.company }</td>
 		 	<td>${j.address }</td>
 		 	<td>${j.salary }</td>
 		 	<td>${j.url }</td>
 		 	<td>${j.limit }</td>
 		 	<td>${j.time }</td>
 		 	<td>${j.desc }</td>
 		 	<td>${j.jobHandle }</td>
 		 	<td>${j.addressHandle }</td>
 		</tr>
 		</c:forEach>
 	</table>
 	 <!-- 自定义标签分页按钮 -->
 	<z:page pageBean="${pageBean }"/>
 	
</body>
</html>

总结

通用分页更简化了代码,不用每个对象都再写一遍dao方法增删改查,只要写一遍,其他对象都可以调用。

你可能感兴趣的:(笔记)