IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> PHP知识库 -> 自定义MVC增删改查应用 -> 正文阅读

[PHP知识库]自定义MVC增删改查应用

1.思维导图:

?

2.解决框架配置文件名及放置问题:

?2.1 中央控制器(DispatchServlet)代码:

? ?如果web.xml没有配置就默认自己写的文件名为准

package com.leijiajia.framework;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.beanutils.PropertyUtils;

import com.leijiajia.web.GoodsAction;
/**
 * 目标:
 * 	根据自定义MVC框架的原理图完成 框架的研发
 *  
 * @author zjjt
 * 
 * 中央控制器
 *   目标:寻找子控制器
 *
 */

/*@WebServlet("*.action")*/
public class DispatchServlet extends HttpServlet {
	//专门存放子控制器的容器 
	//private Map<String, ActionSupport> actions=new HashMap<String, ActionSupport>();
	private ConfigModel configModel = null;
	//初始化子控制器容器(集合),经过初始化,actions容器内部就有了子控制器
	//init,service,destroy
	/**
	 * 需求:
	 *  在增加一个商品类的增删改查
	 * 步骤:
	 *  改动init中代码
	 * 思考:
	 *  能不能不改动代码完成这个需求
	 *   1.参考DBAcess的数据源配置文件config.prooerties
	 *    1.1 减少代码改动风险性
	 *    1.2 减少代码的编译次数(对于已经部署到服务器后)
	 * 解决方案:
	 *  改成子控制器可配置 
	 * 解决步骤:
	 *  1.必须有配置文件config.xml
	 *  2.配置文件config.xml中要包含处理业务的子控制器
	 *  3.读取到配置文件config.xml中的对应的处理浏览器请求的子控制器
	 * 编码:
	 *  ...  
	 */
	
	@Override
	public void init() throws ServletException {
		//缺陷:需要改动原有代码,伴随着很大的风险
		try {
			//配置的位置:web.xml
			String configurationLocation = this.getInitParameter("configurationLocation");
			if(configurationLocation==null || "".equals(configurationLocation)) {
				configurationLocation="/zking.xml";
			}
			configModel=ConfigModelFactory.build(configurationLocation);
		} catch (Exception e) {
			e.printStackTrace();
		}
		
//		actions.put("/book", new BookAction());
//		actions.put("/goods", new GoodsAction());
//		actions.put("/OrderItme", new BookAction());
	}
	
	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		doPost(req, resp);
	}

	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		//完成寻找子控制器的过程
		//浏览器:http://localhost:8080/t266_mvc/book.action?methodName=add
		//目标:BookAction.add()...
		/**
		 * 思路:
		 *  1.从浏览器URL中获取到“book”字符串
		 *  2.在子控制器容器中拿到BookAction
		 *  3.BookAction.add()
		 */
		
		/**
		 * Debug的使用效果:
		 *   1.调试代码(找错)
		 *   2.观看\观察代码的一个流程走向,每一个参数的值
		 */
		
		String uri = req.getRequestURI();
		uri = uri.substring(uri.lastIndexOf("/"), uri.lastIndexOf("."));
		//System.out.println(uri);
		//action=BookAction
		//ActionSupport action = actions.get(uri);
		ActionModel actionModel = configModel.pop(uri);
		String type = actionModel.getType();
		ActionSupport action;
		try {
			//放射实例化
			action = (ActionSupport) Class.forName(type).newInstance();
			//ActionSupport action=new BookAction();
			if(action instanceof ModelDriver) {
				ModelDriver m=(ModelDriver) action;
				Object obj = m.getModel();
				
				//有对象
				//接收所有的前端jsp传递到后台的参数
				Map<String, String[]> parameterMap = req.getParameterMap();
				//给对象赋值
				//PropertyUtils.getProperty(obj, "");
				BeanUtils.populate(obj, parameterMap);
			}
			//execute->delete
			String res = action.execute(req, resp);
			
			/**
			 * 思路:
			 * 1.方法执行宪法完毕必须有一个返回值
			 * 2.通过返回值决定是否重定向还是转发
			 * 3.通过返回值决定跳转那一页
			 */
			ForwardModel forwardModel = actionModel.pop(res);
			if(forwardModel.isRedirect()) {
				//重定向
				resp.sendRedirect(req.getContextPath()+forwardModel.getPath());
			}
			else {
				//转发
				req.getRequestDispatcher(forwardModel.getPath()).forward(req, resp);
			}
		} catch (Exception e) {
			e.printStackTrace();
		} 
		
		
	}

}

2.2 运行结果:

?

3.通用的增删改:

3.1 BaseDao代码:

package com.leijiajia.util;

import java.lang.reflect.Field;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

import com.leijiajia.util.DBAccess;
import com.leijiajia.util.PageBean;
import com.leijiajia.util.StringUtils;

/**
 * 所有Dao层的父类
 *
 * @param <T>
 */
public class BaseDao<T> {
	
	/**
	 * 通用的增删改
	 * @param sql	具体的增删改SQL
	 * @param t		具体要操作的表对应实体类
	 * @param attrs	具体操作表的某些字段对应的实体类属性
	 * @throws Exception 
	 */
	public void executeUpdate(String sql, T t, String[] attrs) throws Exception {
		//?->sid;?->sname;?->remark;
		//attrs = new String[] {"sid","sname","remark"};
		Connection con = DBAccess.getConnection();
		PreparedStatement pst = con.prepareStatement(sql);
		/*pst.setObject(1, student.getSid());
		pst.setObject(2, student.getSname());
		pst.setObject(3, student.getRemark());*/
		//遍历
		for (int i = 0; i < attrs.length; i++) {
			//attrs[0]=sid;attrs[1]=sname;
			Field f = t.getClass().getDeclaredField(attrs[i]);
			f.setAccessible(true);
			//f.get(t);		sid.get(student)
			pst.setObject(i+1, f.get(t));
		}
		pst.executeUpdate();
	}
	
	/**
	 * 通用分页查询
	 * @param sql
	 * @param clz
	 * @return
	 * @throws Exception
	 */
	public List<T> executeQuery(String sql,Class<T> clz,PageBean pageBean) throws Exception{
		List<T> list = new ArrayList<T>();
		Connection con = DBAccess.getConnection();;
		PreparedStatement pst = null;
		ResultSet rs = null;
		
		/*
		 * 是否需要分页?
		 * 	无需分页(项目中的下拉框,查询条件教员下拉框,无须分页)	
		 * 	必须分页(项目中列表类需求、订单列表、商品列表、学生列表...)
		 */
		if(pageBean != null && pageBean.isPagination()) {
//			必须分页(列表需求)
			String countSQL = getCountSQL(sql);
			pst = con.prepareStatement(countSQL);
			rs = pst.executeQuery();
			if(rs.next()) {
				pageBean.setTotal(String.valueOf(rs.getObject(1)));
			}
			
//			挪动到下面,是因为最后才处理返回的结果集
//			-- pageSql=sql limit (page-1)*rows,rows 	对应某一页的数据
//			-- countSql=select count(1) from (sql) t 	符合条件的总记录数
			String pageSQL = getPageSQL(sql,pageBean);//符合条件的某一页数据
			pst = con.prepareStatement(pageSQL);
			rs = pst.executeQuery();
		}else {
//			不分页(select需求)
			pst = con.prepareStatement(sql);//符合条件的所有数据
			rs = pst.executeQuery();
		}
		
		
		while (rs.next()) {
			T t = clz.newInstance();
			Field[] fields = clz.getDeclaredFields();
			for (Field f : fields) {
				f.setAccessible(true);
				f.set(t, rs.getObject(f.getName()));
			}
			list.add(t);
		}
		return list;
	}

	/**
	 * 将原生SQL转换成符合条件的总记录数countSQL
	 * @param sql
	 * @return
	 */
	private String getCountSQL(String sql) {
//		-- countSql=select count(1) from (sql) t 	符合条件的总记录数
		return "select count(1) from ("+sql+") t";
	}

	/**
	 * 将原生SQL转换成pageSQL
	 * @param sql
	 * @param pageBean
	 * @return
	 */
	private String getPageSQL(String sql,PageBean pageBean) {
//		(this.page - 1) * this.rows
//		pageSql=sql limit (page-1)*rows,rows
		return sql + " limit "+ pageBean.getStartIndex() +","+pageBean.getRows();
	}
}

4.增删改的Dao层实现:

4.1 StudentDao(方法类)代码:

4.2 运行结果:

?

5.增删改查代码完整实现:

?5.1 BaseDao代码:

package com.leijiajia.util;

import java.lang.reflect.Field;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

import com.leijiajia.util.DBAccess;
import com.leijiajia.util.PageBean;
import com.leijiajia.util.StringUtils;

/**
 * 所有Dao层的父类
 *
 * @param <T>
 */
public class BaseDao<T> {
	
	/**
	 * 通用的增删改
	 * @param sql	具体的增删改SQL
	 * @param t		具体要操作的表对应实体类
	 * @param attrs	具体操作表的某些字段对应的实体类属性
	 * @throws Exception 
	 */
	public void executeUpdate(String sql, T t, String[] attrs) throws Exception {
		//?->sid;?->sname;?->remark;
		//attrs = new String[] {"sid","sname","remark"};
		Connection con = DBAccess.getConnection();
		PreparedStatement pst = con.prepareStatement(sql);
		/*pst.setObject(1, student.getSid());
		pst.setObject(2, student.getSname());
		pst.setObject(3, student.getRemark());*/
		//遍历
		for (int i = 0; i < attrs.length; i++) {
			//attrs[0]=sid;attrs[1]=sname;
			Field f = t.getClass().getDeclaredField(attrs[i]);
			f.setAccessible(true);
			//f.get(t);		sid.get(student)
			pst.setObject(i+1, f.get(t));
		}
		pst.executeUpdate();
	}
	
	/**
	 * 通用分页查询
	 * @param sql
	 * @param clz
	 * @return
	 * @throws Exception
	 */
	public List<T> executeQuery(String sql,Class<T> clz,PageBean pageBean) throws Exception{
		List<T> list = new ArrayList<T>();
		Connection con = DBAccess.getConnection();;
		PreparedStatement pst = null;
		ResultSet rs = null;
		
		/*
		 * 是否需要分页?
		 * 	无需分页(项目中的下拉框,查询条件教员下拉框,无须分页)	
		 * 	必须分页(项目中列表类需求、订单列表、商品列表、学生列表...)
		 */
		if(pageBean != null && pageBean.isPagination()) {
//			必须分页(列表需求)
			String countSQL = getCountSQL(sql);
			pst = con.prepareStatement(countSQL);
			rs = pst.executeQuery();
			if(rs.next()) {
				pageBean.setTotal(String.valueOf(rs.getObject(1)));
			}
			
//			挪动到下面,是因为最后才处理返回的结果集
//			-- pageSql=sql limit (page-1)*rows,rows 	对应某一页的数据
//			-- countSql=select count(1) from (sql) t 	符合条件的总记录数
			String pageSQL = getPageSQL(sql,pageBean);//符合条件的某一页数据
			pst = con.prepareStatement(pageSQL);
			rs = pst.executeQuery();
		}else {
//			不分页(select需求)
			pst = con.prepareStatement(sql);//符合条件的所有数据
			rs = pst.executeQuery();
		}
		
		
		while (rs.next()) {
			T t = clz.newInstance();
			Field[] fields = clz.getDeclaredFields();
			for (Field f : fields) {
				f.setAccessible(true);
				f.set(t, rs.getObject(f.getName()));
			}
			list.add(t);
		}
		return list;
	}

	/**
	 * 将原生SQL转换成符合条件的总记录数countSQL
	 * @param sql
	 * @return
	 */
	private String getCountSQL(String sql) {
//		-- countSql=select count(1) from (sql) t 	符合条件的总记录数
		return "select count(1) from ("+sql+") t";
	}

	/**
	 * 将原生SQL转换成pageSQL
	 * @param sql
	 * @param pageBean
	 * @return
	 */
	private String getPageSQL(String sql,PageBean pageBean) {
//		(this.page - 1) * this.rows
//		pageSql=sql limit (page-1)*rows,rows
		return sql + " limit "+ pageBean.getStartIndex() +","+pageBean.getRows();
	}
}

5.2 StudentAction 代码(子控制器):?

package com.leijiajia.web;

import java.util.List;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.leijiajia.dao.StudentDao;
import com.leijiajia.entity.Student;
import com.leijiajia.framework.ActionSupport;
import com.leijiajia.framework.ModelDriver;
import com.leijiajia.util.PageBean;

/**
 * 子控制器
 * @author zjjt
 *
 */
public class StudentAction extends ActionSupport implements ModelDriver<Student>{
	//操作的实体类定义在外面
	private Student student=new Student();
	private StudentDao studentDao=new StudentDao();
	
	
	@Override
	public Student getModel() {
		
		return student;
	}

	public String add(HttpServletRequest req, HttpServletResponse resp) {
		try {
			studentDao.add(student);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return "toList";
	}
	
	
	public String delete(HttpServletRequest req, HttpServletResponse resp) {
		try {
			studentDao.delete(student);
		} catch (Exception e) {
			e.printStackTrace();
		}	
		return "toList";
	}
	
	
	public String edit(HttpServletRequest req, HttpServletResponse resp) {
		try {
			studentDao.edit(student);;
		} catch (Exception e) {
			e.printStackTrace();
		}
		return "toList";
	}
	
	
	public String list(HttpServletRequest req, HttpServletResponse resp) {
		PageBean pageBean=new PageBean();
		pageBean.setRequest(req);
		try {
			List<Student> list = studentDao.list(student, pageBean);
			req.setAttribute("students", list);
			req.setAttribute("pageBean", pageBean);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return "list";
	}
	
	public String toEdit(HttpServletRequest req, HttpServletResponse resp) {
		//如果跳转的新增界面	无需查询,如果跳转的是修改界面,需要查询当前sid对应的数据,回显到界面
		if(student.getSid()!=0) {//修改
			try {
				List<Student> list = studentDao.list(student, null);//根据id查询,有且只有一条数据
				req.setAttribute("b", list.get(0));
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		return "toEdit";
	}
	
}

?

5.2 运行结果:

?

6.编写代码过程的报错:

6.1 图片截图:

?

6.2 报错原因:

?mvc.xml需改成configurationLocation

?6.3 报错截图:

?6.4 报错原因:

? ? ?驱动包导错了

?6.5 报错截图:

?6.6 报错原因:

需要把con.zking.tag.PageTag该为自己包路径

?

?6.6 报错截图:

??6.7 报错原因:

地址栏中的?methodName写错了,导致页面不显示

?

7.视图层:

?studentList.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
<%@ taglib uri="http://jsp.veryedu.cn" prefix="z"%>	
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>	
<!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>
<style type="text/css">
.page-item input {
	padding: 0;
	width: 40px;
	height: 100%;
	text-align: center;
	margin: 0 6px;
}

.page-item input, .page-item b {
	line-height: 38px;
	float: left;
	font-weight: 400;
}

.page-item.go-input {
	margin: 0 10px;
}
</style>
</head>
<body>
	<form class="form-inline"
		action="${pageContext.request.contextPath }/student.action?methodName=list" method="post">
		<div class="form-group mb-2">
			<input type="text" class="form-control-plaintext" name="sname"
				placeholder="请输入学生名字">
<!-- 			<input name="rows" value="20" type="hidden"> -->
<!-- 不想分页 -->
				<input name="pagination" value="false" type="hidden">
		</div>
		<button type="submit" class="btn btn-primary mb-2">查询</button>
		<a class="btn btn-primary mb-2" href="${pageContext.request.contextPath }/student.action?methodName=toEdit">新增</a>
	</form>

	<table class="table table-striped">
		<thead>
			<tr>
				<th scope="col">学生ID</th>
				<th scope="col">学生名</th>
				<th scope="col">学生备注</th>
				<th scope="col">操作</th>
			</tr>
		</thead>
		<tbody>
			<c:forEach  var="b" items="${students }">
			<tr>
				<td>${b.sid }</td>
				<td>${b.sname }</td>
				<td>${b.remark }</td>
				<td>
					<a href="${pageContext.request.contextPath }/student.action?methodName=toEdit&sid=${b.sid}">修改</a>
					<a href="${pageContext.request.contextPath }/student.action?methodName=delete&sid=${b.sid}">删除</a>
				</td>
			</tr>
			</c:forEach>
		</tbody>
	</table>
	<!-- 这一行代码就相当于前面分页需求前端的几十行了 -->
	<z:page pageBean="${pageBean }"></z:page>

</body>
</html>

?8.配置mvc.xml

<?xml version="1.0" encoding="UTF-8"?>
<config>
	<action path="/student" type="com.leijiajia.web.StudentAction">
		<forward name="list" path="/studentList.jsp" redirect="false" />
<!-- 		增删改操作之后要再一次查询数据库的新的数据做展示 -->
		<forward name="toList" path="/student.action?methodName=list" redirect="true" />
		<forward name="toEdit" path="/studentEdit.jsp" redirect="false" />
	</action>
</config>

  PHP知识库 最新文章
Laravel 下实现 Google 2fa 验证
UUCTF WP
DASCTF10月 web
XAMPP任意命令执行提升权限漏洞(CVE-2020-
[GYCTF2020]Easyphp
iwebsec靶场 代码执行关卡通关笔记
多个线程同步执行,多个线程依次执行,多个
php 没事记录下常用方法 (TP5.1)
php之jwt
2021-09-18
上一篇文章      下一篇文章      查看所有文章
加:2021-09-04 17:17:00  更:2021-09-04 17:19:24 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年12日历 -2024/12/29 19:26:07-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码
数据统计