自定义mvc实现增删改查
一、前言
我在之前的博客中已经向大家介绍了自定义mvc的基本知识。还不是很了解的可以看一下之前的博客。
传送门在此: https://blog.csdn.net/qq_45547474/article/details/106531932.
那么这次我就给大家讲解一下用自定义mvc来解决增删改查。
首先了解一下servlet是如何解决增删改查的。
二、用servlet解决增删改查
1、servlet解决代码方式简单了解
那我们先看到一个类列表,我们可以了解到为了完成一个增删改查,使用servlet会显得代码很多,极其繁琐。
我们调出一段servlet查询需求的代码看一下:
//zouyan
public List<Book> getAll(Book b,PageBean pageBean) throws SQLException{
List<Book> ls=new ArrayList<Book>();
String sql="select * from t_mvc_book where true";
String bname = b.getBname();
if(StringUtils.isNotBlank(bname)) {
sql+=" and bname like '%"+bname+"%'";
}
Connection con=DBAccess.getConnection();
PreparedStatement ps = con.prepareStatement(sql);
ResultSet rs=ps.executeQuery();
while(rs.next()) {
ls.add(new Book(rs.getInt("bid"),rs.getString("bname"),rs.getFloat("price")));
}
DBAccess.close(con, ps, rs);
return ls;
}
可以看出代码的一个很明显的弊端 : if条件分支过多,代码过于臃肿。
包括还有界面和jar包,相对于自定义mvc解决增删改查来说servlet解决会简单很多。因为servlet存在很多的弊端。
2、弊端
1、if条件分支过多,代码过于臃肿
2、处理前端jsp传递到后端值得封装代码量过大
3、处理完业务逻辑应该跳转指定页面
但是自定义mvc却很好的可以解决 :
(自定mvc)
1、if条件分支过多,代码过于臃肿
分析:if代码块中就是调用了当前类的对应方法
处理:反射动态调用方法
2、处理前端jsp传递到后端值得封装代码量过大
分析:给指定的类属性赋值
处理:通过反射读写属性
3、处理完业务逻辑应该跳转指定页面
分析:不同的逻辑处理完要跳转的页面不同,代码的位置过于混乱,我们希望同一管理
处理:xml建模将结果页面统一配置
那么我们就通过代码来了解吧。
三、自定义mvc解决增删改查
1、步骤解读
使用到的工具:mysql+eclipse
利用mvc完成增删改
那我们就按照步骤来完成吧。
2、代码了解
首先来完成实体类的代码,你需要完成什么代码就写上什么属性就可以了。
我所操纵的是一个job表
那么实体类代码就是这样写的:
//zouyan
/**
* 招聘信息的实体类
* @author zouyan
*
* Orange_南橙
*/
public class Recruitment{
private String id;
private String job;
private String company;
private String address;
private String salary;
private String url;
private String limit;
private Date time;
private String desc;
private String jobHandle;
private String addressHandle;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getJob() {
return job;
}
public void setJob(String job) {
this.job = job;
}
public String getCompany() {
return company;
}
public void setCompany(String company) {
this.company = company;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public String getSalary() {
return salary;
}
public void setSalary(String salary) {
this.salary = salary;
}
public String getLimit() {
return limit;
}
public void setLimit(String limit) {
this.limit = limit;
}
public Date getTime() {
return time;
}
public void setTime(Date time) {
this.time = time;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public String getDesc() {
return desc;
}
public void setDesc(String desc) {
this.desc = desc;
}
public String getJobHandle() {
return jobHandle;
}
public void setJobHandle(String jobHandle) {
this.jobHandle = jobHandle;
}
public String getAddressHandle() {
return addressHandle;
}
public void setAddressHandle(String addressHandle) {
this.addressHandle = addressHandle;
}
@Override
public String toString() {
return "Recruitment [id=" + id + ", job=" + job + ", company=" + company + ", address=" + address + ", salary="
+ salary + ", url=" + url + ", limit=" + limit + ", time=" + time + ", desc=" + desc + ", jobHandle="
+ jobHandle + ", addressHandle=" + addressHandle + "]";
}
public Recruitment(String id, String job, String company, String address, String salary, String url, String limit,
Date time, String desc, String jobHandle, String addressHandle) {
this.id = id;
this.job = job;
this.company = company;
this.address = address;
this.salary = salary;
this.url = url;
this.limit = limit;
this.time = time;
this.desc = desc;
this.jobHandle = jobHandle;
this.addressHandle = addressHandle;
}
public Recruitment() {}
}
然后实体类完成之后,就是dao层里面的代码了。
//zouyan
public class BaseDao<K> {
public List<K> executeQuery(String sql, Class clz,PageBean pagebean) throws Exception{
List<K> ls=new ArrayList<K>();
Connection con = DBAccess.getConnection();
PreparedStatement ps = con.prepareStatement(sql);
ResultSet rs=null;
if(pagebean!=null && pagebean.isPagination()) {
//想分页
String countSql=getCountSql(sql);
ps = con.prepareStatement(countSql);
rs=ps.executeQuery();
if(rs.next()) {
pagebean.setTotal(rs.getObject(1).toString());
}
//展示想要看到的数据 比如说第三条的数据
String pageSql=getPageSql(sql,pagebean);
ps = con.prepareStatement(pageSql);
rs=ps.executeQuery();
}else {
//不想分页
ps = con.prepareStatement(sql);
rs=ps.executeQuery();
}
while(rs.next()) {
//ls.add(new Book(rs.getInt("bid"), rs.getString("bname"), rs.getString("price")));
K k=(K)clz.newInstance();
//Field[] fields = clz.getDeclaredFields();
for (Field f : clz.getDeclaredFields()) {
f.setAccessible(true);
f.set(k, rs.getObject(f.getName()));
}
ls.add(k);
}
DBAccess.close(con, ps, rs);
return ls;
}
public int executeUpdate(String sql,K k,String attrs[]) throws SQLException, NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException {
Connection con=DBAccess.getConnection();
PreparedStatement ps = con.prepareStatement(sql);
/*ps.setObject(1, book.getBid());
ps.setObject(2, book.getBname());
ps.setObject(3, book.getPrice());*/
//以上三行代码的意思是,将参数t中的属性值,赋值给object对象
int loop=1;
Field f= null;
//attrs 属性值
for (String attr : attrs) {
f=k.getClass().getDeclaredField(attr);
f.setAccessible(true);
ps.setObject(loop++, f.get(k));
}
int n=ps.executeUpdate();
DBAccess.close(con, ps, null);
return n;
}
private String getCountSql(String sql) {
// TODO Auto-generated method stub
return "select count(1) from ("+sql+") t";
}
private String getPageSql(String sql, PageBean pagebean) {
// TODO Auto-generated method stub
return sql+" limit "+pagebean.getStartIndex()+","+pagebean.getRows();
}
}
然后dao层的好了之后,看到web层的代码。web层的就要考虑增删改查的查询了。
//zouyan
public class RecruitmentServlet extends ActionSupport implements ModelDriven<Recruitment>{
private static final long serialVersionUID = 1L;
private Recruitment r=new Recruitment();
public RecruitmentDao rd=new RecruitmentDao();
public String list(HttpServletRequest req, HttpServletResponse resp) throws Exception {
Recruitment re=new Recruitment();
req.setCharacterEncoding("utf-8");
String name=req.getParameter("name");
re.setCompany(name);
PageBean pageBean=new PageBean();
pageBean.setRequest(req);
req.setAttribute("pageBean", pageBean);
try {
List<Recruitment> ls= rd.list(re, pageBean);
req.setAttribute("recruitment", ls);
req.setAttribute("name", name);
req.getRequestDispatcher("/index.jsp").forward(req, resp);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return "list";
}
//新增
public String add(HttpServletRequest req, HttpServletResponse resp) throws Exception {
rd.add(r);
return "toList";
}
//删除
public String del(HttpServletRequest req, HttpServletResponse resp) throws Exception {
rd.del(r);
return "toList";
}
//修改
public String edit(HttpServletRequest req, HttpServletResponse resp) throws Exception {
rd.edit(r);
return "toList";
}
//跳转修改
public String toEdit(HttpServletRequest req, HttpServletResponse resp) throws Exception {
Recruitment re=this.rd.list(r, null).get(0);
req.setAttribute("r", re);
return "toEdit";
}
//查询单个
public String one(HttpServletRequest req, HttpServletResponse resp) throws Exception {
Recruitment re=this.rd.list(r, null).get(0);
req.setAttribute("Recruitment", re);
return "toOne";
}
@Override
public Recruitment getModel() {
// TODO Auto-generated method stub
return r;
}
}
ok之后,记得对xml进行修改,因为很多时候就会忘记修改xml里面的路径:
最后就是界面jsp的代码了。
//zouyan
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@taglib prefix="z" uri="/zouyan" %>
<!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">
<link href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/4.5.0/css/bootstrap.css" rel="stylesheet">
<script src="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/4.5.0/js/bootstrap.js"></script>
<title>主界面</title>
</head>
<body>
<form action="${pageContext.request.contextPath }/recruitment.action?methodName=list" method="post">
<input name="name" type="text" value="${name }" />
<input type="submit" value="查询" />
</form>
<table border="1px" width="100%" >
<tr>
<td align="center">职位</td>
<td align="center">公司</td>
<td align="center">工作地址</td>
<td align="center">薪资</td>
<td align="center">学历要求</td>
<td align="center">爬取时间</td>
<td align="center">查看详情</td>
</tr>
<c:forEach items="${recruitment}" var="r" >
<tr>
<td align="center">${r.job}</td>
<td align="center">${r.company }</td>
<td align="center">${r.address }</td>
<td align="center">${r.salary }</td>
<td align="center">${r.limit }</td>
<td align="center">${r.time }</td>
<td align="center">
<a href="${pageContext.request.contextPath }/recruitment.action?methodName=one&id=${r.id}">查看详情</a>
</td>
</tr>
</c:forEach>
</table>
<z:page pageBean="${pageBean }"></z:page>
<a href="add.jsp">增加</a>
</body>
</html>
然后,还会有增加界面和修改界面的一个界面显示。我就不在这里做详细讲解了。
1.分页工具包
分页工具包是可以用到分页代码里的,类似一个大工厂,拿过去就可以了。方便至极。
//zouyan
package com.zouyan.util;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
/**
* 分页工具类
*
*/
public class PageBean {
private int page = 1;// 页码
private int rows = 10;// 页大小
private int total = 0;// 总记录数
private boolean pagination = true;// 是否分页
//上一次查询所携带的查询条件
private Map<String, String[]> parameterMap=new HashMap<String, String[]>();
//上一次查询的url
private String url;
public void setRequest(HttpServletRequest req) {
//初始化jsp页面传递过来的当前页
this.setPage(req.getParameter("page"));
//初始化jsp页面传递过来的页大小
this.setRows(req.getParameter("rows"));
//初始化jsp页面传递过来的是否分页
this.setPagination(req.getParameter("pagination"));
//保留上一次的查询请求
this.setUrl(req.getRequestURI().toString());
//保留上一次的查询条件
this.setParameterMap(req.getParameterMap());
}
private void setPagination(String parameter) {
//只有填写了false才代表不分页
this.setPagination(!"false".equals(parameter));
}
private void setRows(String parameter) {
if(StringUtils.isNotBlank(parameter))
this.rows=(Integer.valueOf(parameter));
}
private void setPage(String parameter) {
if(StringUtils.isNotBlank(parameter))
this.page=(Integer.valueOf(parameter));
}
public Map<String, String[]> getParameterMap() {
return parameterMap;
}
public void setParameterMap(Map<String, String[]> parameterMap) {
this.parameterMap = parameterMap;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public PageBean() {
super();
}
public int getPage() {
return page;
}
public void setPage(int page) {
this.page = page;
}
public int getRows() {
return rows;
}
public void setRows(int rows) {
this.rows = 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;
}
/**
* 获得起始记录的下标
*
* @return
*/
public int getStartIndex() {
return (this.page - 1) * this.rows;
}
@Override
public String toString() {
return "PageBean [page=" + page + ", rows=" + rows + ", total=" + total + ", pagination=" + pagination + "]";
}
//上一页
public int getPrevPage() {
return this.page>1?this.page-1:this.page;
}
//下一页
public int getNextPage() {
return this.page < this.getMaxPage()? this.page+1:this.page;
}
//最大页
public int getMaxPage() {
return this.total % this.rows == 0 ? this.total/this.rows : (this.total/this.rows)+1;
}
}
3、界面展示
主界面展示如下:
注:界面可以自己通过样式去进行调整哦,包括字体颜色、表格宽度等。
下面是我的一个jar包展示和列表展示:
四、总结
然后自定义mvc的增删改查就可以实现了,此后可以更深入去了解这方面的学习。继续加油吧。
我是南橙,一个逐渐秃头的橙子Orange。