前言
今天来打包自己的框架和使用框架其实本质上是一个山寨的Struts2框架,但是这是自己写的满足感爆棚!!基于前面博客写了框架的原理和运行流程,这里就不在重复了。
贴上链接:
文章 | 地址 |
---|---|
通用分页 | https://editor.csdn.net/md/?articleId=106578191 |
自定义mvc | https://blog.csdn.net/qq_45384482/article/details/106528330 |
1.自定义框架实现增删改查
1.1准备工作
xml的配置两部曲
1.字符编码过滤器
2.中央控制器
tld的配置
1.2代码部分
BaseDao
这一部分是前面没有的 ,增删改的共性就是返回受影响行数,通过反射实现了增删改的通用。
传过来sql语句和指定对象以及对象的属性数组,这里对象声明了泛型支持通用,然后传过来对象对应的属性
数组进行循环赋值,最后执行获得受影响行数。
//通用增删改
public int executeUpdate(String sql,T t,String attrs[]) throws NoSuchFieldException, SecurityException, SQLException, IllegalArgumentException, IllegalAccessException {
//获取连接
Connection con=DBAccess.getConnection();
//预处理对象
PreparedStatement ps=con.prepareStatement(sql);
int loop=1;//定义对应列的下标
Field f=null;//定义属性
//获取对象属性反射赋值
for (String attr : attrs) {
f=t.getClass().getDeclaredField(attr);//通过类对象获取属性对象
f.setAccessible(true);//打开权限
ps.setObject(loop++, f.get(t));//根据属性对象获取对象的属性值
}
int code=ps.executeUpdate();//执行
//关闭连接
DBAccess.close(con, ps,null);
//返回受影响行数
return code;
}
框架配置文件
核心点:增/删/改用重定向,查询用转发
概述大致流程:
Dao类
注意点:
这是数据库表
这里增加的方式两种
1.新增招聘的sql语句对应指定列名
“insert into t_solr_job(id,job,company,address,salary,limitd,time) values(?,?,?,?,?,?,?)”;
2.新增插入当前表的所有列
"insert into t_solr_job values(?,?,?,?,?,?,?,?,?,?)
return super.executeUpdate(sql, job, new String[] { “id”, “job”, “company”, “address”, “salary”, “limitd”, “time”, “desc” , “jobHandle” , “addressHandle” });
踩坑打卡:
错误示范:“insert into t_solr_job values(?,?,?,?,?,?,?)”;
我的实体类:
抛出:Column count doesn’t match value count at row 1
错误:列计数与第1行上的值计数不匹配
原因:参考以上表可以看出来我实体类不数据库的属性少三个,sql语法这时本身就是错误语法了。
随机id
语法 | 意思 |
---|---|
UUID.randomUUID().toString() | 随机生成一个64位的字符串型的id |
package com.liyingdong.dao;
import java.sql.SQLException;
import java.util.List;
import java.util.UUID;
import com.liyingdong.entity.Job;
import com.liyingdong.util.PageBean;
import com.liyingdong.util.StringUtils;
/**
* dao类
* @author 李瀛东
* 2020年6月8日
*/
public class JobDao extends BaseDao<Job> {
/**
* 增加
*
* @param job对象
* @return 返回受影响行数
*/
public int add(Job job) throws NoSuchFieldException, SecurityException, IllegalArgumentException,
IllegalAccessException, SQLException {
// jsp没有向后台传入id 调用方法自动生成id
job.setId(UUID.randomUUID().toString());
String sql = "insert into t_solr_job(id,job,company,address,salary,limitd,time) values(?,?,?,?,?,?,?)";
return super.executeUpdate(sql, job,
new String[] { "id", "job", "company", "address", "salary", "limitd", "time" });
}
/**
* 删除
* @param job
* @return 返回受影响行数
*/
public int del(Job job) throws NoSuchFieldException, SecurityException, IllegalArgumentException,
IllegalAccessException, SQLException {
String sql = "delete from t_solr_job where id=?";
return super.executeUpdate(sql, job, new String[] { "id" });
}
/**
* 修改
* @param job对象
* @return 返回受影响行数
*/
public int update(Job job) throws NoSuchFieldException, SecurityException, IllegalArgumentException,
IllegalAccessException, SQLException {
String sql = "update t_solr_job set job=?,company=?,address=?,salary=?,limitd=?,time=? where id=? ";
return super.executeUpdate(sql, job,
new String[] { "job", "company", "address", "salary", "limitd", "time", "id" });
}
/**
* 分页
* @param job对象
* @param pageBean分页对象
* @return 返回受影响行数
*/
public List<Job> list(Job job, PageBean pageBean)
throws SQLException, InstantiationException, IllegalAccessException {
String sql = "select *from t_solr_job where true ";
String bname = job.getCompany();
// 判断是否要模糊查询
if (StringUtils.isNotBlank(bname)) {
sql += " and company like'%" + bname + "%' ";
}
// 进行单个查询的时候
if (null != job.getId()) {
sql += " and id='" + job.getId() + "' ";
}
// 调用通用分页方法并返回数据
return super.executeQuery(sql, Job.class, pageBean);
}
}
JobAction控制层
这里声明一下这个异常的使用
1.套第一种异常的话你肯定会被项目组长叼的。
2.套第二种才是规范的。
原因:对症下药,专业的事找专业的人做,第一种的话不管你几个错它只会抛出一个,第二种你报几个错抛几
个错抛出对应的错。
第一种:
第二种:
package com.liyingdong.action;
import java.sql.SQLException;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.liyingdong.dao.JobDao;
import com.liyingdong.entity.Job;
import com.liyingdong.framework.DispatcherAction;
import com.liyingdong.framework.ModelDriver;
import com.liyingdong.util.PageBean;
/**
* CalAction是子控制器
* 可以理解为具体做事的那个人,能做事的前提下是有资格证,所有必须继承Action
* 现在子控制器继承的是DispatcherAction方法分发类,同时方法分发类继承了Action所以是一样的道理
* 而且实现ModelDriver类是一个oop思想 进行事务进行对象化
* @author 李瀛东
* 2020年6月3日
*/
public class JobAction extends DispatcherAction implements ModelDriver<Job> {
Job c=new Job();
JobDao j=new JobDao();
/**
* 返回创建好的对象
*/
@Override
public Job getModel() {
return c;
}
/**
* 刷新分页的方法
* @param req
* @param resp
* @return
*/
public String list(HttpServletRequest req, HttpServletResponse resp) {
PageBean pageBean=new PageBean();
JobDao jd=new JobDao();
Job j=new Job();
//获取bname进行模糊查询
j.setCompany(req.getParameter("bname"));
//给分页类初始化
pageBean.setRequest(req);
try {
//调用分页方法获取结果集
List<Job> all = jd.list(j, pageBean);
//存入作用于
req.setAttribute("pageBean",pageBean);
req.setAttribute("JobList", all);
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}
//返回结果码-------->对应的跳转路径为主界面
return "list";
}
/**
* 查询单个
* @param req
* @param resp
* @return 结果码
*/
public String one(HttpServletRequest req, HttpServletResponse resp) throws InstantiationException, IllegalAccessException, SQLException {
//初始化分页和实体类
PageBean pageBean=new PageBean();
JobDao jd=new JobDao();
Job j=new Job();
// 获取id进行赋值
j.setId(req.getParameter("id"));
//初始化分页类
pageBean.setRequest(req);
//获取符合条件的结果集
Job job = this.j.list(j, null).get(0);
//存入作用域
req.setAttribute("one", job);
//返回结果码----------->对应为update.jsp
return "one";
}
/**
* 删除
* @param req
* @param resp
* @return 结果码
*/
public String del(HttpServletRequest req, HttpServletResponse resp) {
c.setId(req.getParameter("id"));
try {
this.j.del(c);
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}
return "success";
}
/**
* 增加
* @param req
* @param resp
* @return 结果码
*/
public String add(HttpServletRequest req, HttpServletResponse resp) {
try {
this.j.add(c);
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}
return "success";
}
/**
* 修改
* @param req
* @param resp
* @return 结果码
*/
public String update(HttpServletRequest req, HttpServletResponse resp) {
try {
this.j.update(c);
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}
return "success";
}
}
ActionServlet中央控制器
package com.liyingdong.framework;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.beanutils.BeanUtils;
public class ActionServlet extends HttpServlet {
/**
* 实现序列化
*/
private static final long serialVersionUID = 1L;
private ConfigModel configModel = null;
/**
* 读取xml进行建模 这个过程放在初始方法里面不管请求多少次(建模过程只有一次)
*/
@Override
public void init() throws ServletException {
// TODO Auto-generated method stub
try {
configModel = ConfigModelFactory.createConfigModelFactory("/mvc.xml");
} catch (Exception e) {
// TODO: handle exception
throw new RuntimeException(e);
}
}
@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
// 1获取请求路径
String servletPath = req.getServletPath();
// 2获得*:子控制器对应的路径
String actionPath = servletPath.substring(0, servletPath.indexOf(".action"));
// 3.根据*获取子控制器 得到子控制器
ActionModel actionModel = configModel.get(actionPath);
// 4.得到type相当于得到完整类名
String type = actionModel.getType();
// 5.根据完整类名拿到子控制器
Action action = getAction(type);
// 6.通过反射赋值
doModelDriver(action, req);
// 7.把请求委托给子控制器执行获取结果码
String code = action.execute(req, resp);
// 8.根据结果码进行流程的转发和重定向
forwardByCode(code, actionModel, req, resp);
}
/**
* 根据完整类名进行反射实例化对象进行强转并且返回对象
*
* @param type
* @return Action
*/
private Action getAction(String type) {
try {
Class<?> c = Class.forName(type);
Action action = (Action) c.newInstance();
return action;
} catch (Exception e) {
// TODO: handle exception
throw new RuntimeException(e);
}
}
/**
* 根据子控制器返回的结果码进行跳转
*
* @param code
* @param actionModel
* @param req
* @param resp
* @throws IOException
* @throws ServletException
*/
private void forwardByCode(String code, ActionModel actionModel, HttpServletRequest req, HttpServletResponse resp)
throws IOException, ServletException {
if (null == code) {// code就是结果码
return;
}
// 根据结果码拿到forwardModel对象
ForwardModel forwardModel = actionModel.get(code);
// 拿到forwardModel对象里面重定向的属性判断
boolean redirect = forwardModel.isRedirect();
// 拿到跳转路径
String path = forwardModel.getPath();
if (redirect) {
// 如果是true就进行重定向
resp.sendRedirect(req.getContextPath()+forwardModel.getPath());
} else {
// 否则进行转发
req.getRequestDispatcher(path).forward(req, resp);
}
}
public void doModelDriver(Action action, HttpServletRequest req) {
// 如果它实现了ModelDriver接口那就实现强转
if (action instanceof ModelDriver) {
// 进行强转
ModelDriver<?> modelDriver = (ModelDriver<?>) action;
// 调方法返回一个java对象
Object obj = modelDriver.getModel();
// TODO: handle exception
try {
// 利用反射赋值的jar进行赋值
BeanUtils.populate(obj, req.getParameterMap());
} catch (Exception e) {
// TODO: handle exception
throw new RuntimeException();
}
}
}
}
方法分发类
package com.liyingdong.framework;
import java.io.IOException;
import java.lang.reflect.Method;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class DispatcherAction extends Action{
@Override
public String execute(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
try {
//反射调用方法
String methodName = req.getParameter("methodName");
//拿到类对象
Class c=this.getClass();
//获取方法对象
Method method= c.getMethod(methodName, HttpServletRequest.class,HttpServletResponse.class);
//执行子控制器的方法拿到结果码并返回
String code=(String)method.invoke(this,req,resp);
return code;
} catch (Exception e) {
// TODO: handle exception
throw new RuntimeException(e);
}
}
}
Action抽象类
package com.liyingdong.framework;
/**
* 模型实体
* @author 李瀛东
*
* 2020年6月3日
*/
public interface ModelDriver <K> {
public K getModel();
}
模型接口
package com.liyingdong.framework;
/**
* 模型实体
* @author 李瀛东
*
* 2020年6月3日
*/
public interface ModelDriver <K> {
public K getModel();
}
1.3JSP部分
index.jsp加载数据
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!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>
<a href="JobAction.action?methodName=list">招聘查询</a>
</body>
</html>
JobList.jsp主界面
<%@ 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="d" uri="/liyingdong"%>
<!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>书籍列表</title>
<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>
<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="JobAction.action?methodName=list" method="post">
<div class="form-group mx-sm-3 mb-2">
<input class="form-control" id="bname" name="bname" placeholder="请输入书籍名称">
<a href="add.jsp"><button type="button" class="btn btn-success">增加 </button></a>
</div>
<button type="submit" class="btn btn-primary mb-2">查询</button>
</form>
<table class="table table-striped">
<thead>
<tr>
<th scope="col">职位</th>
<th scope="col">公司</th>
<th scope="col">工作地址</th>
<th scope="col">薪资</th>
<th scope="col">学历要求</th>
<th scope="col">爬取时间</th>
<th scope="col">操作</th>
</tr>
</thead>
<tbody>
<c:forEach var="b" items="${JobList }">
<tr>
<td>${b.job }</td>
<td>${b.company }</td>
<td>${b.address }</td>
<td>${b.salary }</td>
<td>${b.limitd }</td>
<td>${b.time }</td>
<td>
<a href="JobAction.action?methodName=del&id=${b.id }" onclick="return confirm('您确定要删除吗?')">
<button type="button" class="btn btn-warning" >删除</button>
</a>
<a href="JobAction.action?methodName=one&id=${b.id }">
<button type="button" class="btn btn-warning">修改</button>
</a>
</td>
</tr>
</c:forEach>
</tbody>
</table>
<d:page pageBean="${pageBean }"></d:page>
</body>
</html>
1.4输出结果
删除:
查询:
修改:
2.打包war包和使用
简单的说打包war包其实就是打包项目,放入tomcat是可以直接访问的。
步骤如下:
没毛病直接可以使用
如果要进行局部性的更新直接替换class文件就好了
3.打包框架和使用
项目中的使用
其余的地方一样
配置好xml的两部曲
继承框架中的两个类其余不变
测试:
尾言
好了今天就到此结束了,框架也打包好了对于简单的增删改查能够快速的开发,方便、简单了。