一、 核心思想:各司其职
1. 什么是MVC:
它是一种软件设计典范,用一种业务逻辑、数据、界面显示分离的方法组织代码
Model1 jsp+jdbc Model2 ->MVC
2. MVC结构
model(模型): 实体域模型(名词)、 过程域模型(动词)
view(视图) : jsp/ios/android
controller (控制器) : servlet/action
web 做浏览器请求分发
service 调用dao处理项目业务的
dao 操作数据库
注1:不能跨层调用
注2:只能出现由上而下的调用
3. 自定义MVC工作原理图
主控制器:查看是否有对应的子控制器来处理用户请求,如果就调用子控制器来处理请求;没有就报错,就处理不了请求
子控制器:就是处理用户请求用的
二、自定义mvc的弊端及处理
-
if条件分支过多,代码过于臃肿
分析:if代码块中就是调用了当前类的对应方法
处理:反射动态调用方法 -
处理前端jsp传递到后端值得封装代码量过大
分析:说白就是给指定的类属性赋值
处理:通过反射读写属性 -
处理完业务逻辑应该跳转指定页面
分析:不同的逻辑处理完要跳转的页面不同,代码的位置过于混乱,我们希望同一管理
处理:xml建模将结果页面统一配置
三、案例
处理if分支问题,动态调用当前类的其他方法add/del/edit:
public class ActionSupport implements Action {
@Override
public String execute(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException, NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
String methodName = req.getParameter("methodName");
// this指的是BookAction
Method m=this.getClass().getDeclaredMethod(methodName, HttpServletRequest.class,HttpServletResponse.class);
m.setAccessible(true);
// 相当于动态调用del(req,resp)
return (String) m.invoke(this, req,resp);
}
}
mvc.xml:
<?xml version="1.0" encoding="UTF-8"?>
<config>
<action path="/book" type="com.jiangjiayan.servlet.BookServlet">
<forward name="list" path="/bookList.jsp" redirect="false" />
<forward name="toAdd" path="/booAdd.jsp" redirect="" />
<forward name="toEdit" path="/bookEdit.jsp" redirect="false" />
<forward name="toList" path="/book.action?methodName=list" redirect="" />
</action>
</config>
注:查询使用转发,增删改使用重定向
dao:
package com.jiangjiayan.dao;
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.jiangjiayan.entity.Book;
import com.jiangjiayan.util.BaseDao;
import com.jiangjiayan.util.DBAccess;
import com.jiangjiayan.util.PageBean;
import com.jiangjiayan.util.StringUtils;
public class BookDao extends BaseDao<Book> {
//通过反射进行通用
public List<Book> list(Book book,PageBean pageBean) throws SQLException, InstantiationException, IllegalAccessException{
String sql="select * from t_mvc_book where 1=1";//这里的1=1也可以true代替
String bname=book.getBname();
int bid=book.getBid();
if(StringUtils.isNotBlank(bname)) {
sql +=" and bname like '%"+bname+"%' ";
}
if(bid!=0) {
sql +=" and bid ="+bid;
}
return super.executeQuery(sql, Book.class, pageBean);
}
//新增
public int add(Book book) throws SQLException, NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException {
String sql="insert into t_mvc_book values(?,?,?)";
return super.executeUpdate(sql, book, new String[] {"bid","bname","price"});
}
//修改
public int edit(Book book) throws SQLException, NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException {
String sql="update t_mvc_book set bname=?,price=? where bid=?";
return super.executeUpdate(sql, book, new String[] {"bname","price","bid"});
}
//删除
public int del(Book book) throws SQLException, NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException {
String sql="delete t_mvc_book where bid=?";
return super.executeUpdate(sql, book, new String[] {"bid"});
}
public static void main(String[] args) throws InstantiationException, IllegalAccessException {
BookDao bookDao=new BookDao();
Book book=new Book();
book.setBname("圣墟");
PageBean pageBean=new PageBean();
pageBean.setPage(2);
try {
List<Book> list = bookDao.list(book, pageBean);
for(Book b:list) {
System.out.println(b);
}
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
BookServlet:
package com.jiangjiayan.servlet;
import java.io.IOException;
import java.sql.SQLException;
import java.util.List;
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 com.jiangjiayan.dao.BookDao;
import com.jiangjiayan.entity.Book;
import com.jiangjiayan.model.ActionSupport;
import com.jiangjiayan.model.ModelDriven;
import com.jiangjiayan.util.PageBean;
//@WebServlet(name="bookServlet",urlPatterns="/bookServlet")
public class BookServlet extends ActionSupport implements ModelDriven<Book> {
private static final long serialVersionUID = 4563046873692541228L;
private BookDao bookDao=new BookDao();
private Book book=new Book();
//
//
// @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 {
// String methodName = req.getParameter("methodName");
// if("list".equals(methodName)) {
// list(req, resp);
// }else if("add".equals(methodName)) {
// add(req, resp);
// }else if("edit".equals(methodName)) {
// edit(req, resp);
// }else if("find".equals(methodName)) {
// find(req, resp);
// }else if("del".equals(methodName)) {
// del(req, resp);
// }
//
// }
private String toAdd(HttpServletRequest req, HttpServletResponse resp) {
return "toAdd";
}
private String add(HttpServletRequest req, HttpServletResponse resp) {
System.out.println("处理书籍新增业务逻辑。。。。。");
try {
this.bookDao.add(book);
} catch (NoSuchFieldException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// Book book=new Book();
// book.setBid(Integer.valueOf(req.getParameter("bid")));
// book.setBname(req.getParameter("bname"));
// book.setPrice(Float.valueOf(req.getParameter("price")));
// bookDao.add(book);
return "toList";
}
private String edit(HttpServletRequest req, HttpServletResponse resp) {
System.out.println("处理书籍修改业务逻辑。。。。。");
try {
this.bookDao.edit(book);
} catch (NoSuchFieldException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return "toList";
}
private String find(HttpServletRequest req, HttpServletResponse resp) {
System.out.println("跳转到修改界面。。。。。");
// try {
// req.getRequestDispatcher("/bookEdit.jsp").forward(req, resp);
// } catch (ServletException e) {
// // TODO Auto-generated catch block
// e.printStackTrace();
// } catch (IOException e) {
// // TODO Auto-generated catch block
// e.printStackTrace();
// }
try {
//修改界面数回息
Book b=this.bookDao.list(book, null).get(0);
req.setAttribute("b", b);
} catch (InstantiationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return "toEdit";
}
private String del(HttpServletRequest req, HttpServletResponse resp) {
System.out.println("处理书籍删除业务逻辑。。。。。");
try {
this.bookDao.del(book);
} catch (NoSuchFieldException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return "toList";
}
private String list(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//设置字符编码
req.setCharacterEncoding("utf-8");
//获取表单值
String bname = req.getParameter("bname");
Book b=new Book();
b.setBname(bname);
PageBean pageBean=new PageBean();
try {
pageBean.setRequest(req);
List<Book> list = this.bookDao.list(b, pageBean);
req.setAttribute("bookList", list);
req.setAttribute("pageBean", pageBean);
// req.getRequestDispatcher("/bookList.jsp").forward(req, resp);
} catch (InstantiationException | IllegalAccessException | SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return "list";
}
@Override
public Book getModel() {
// TODO Auto-generated method stub
return book;
}
}
BaseDao:
package com.jiangjiayan.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.jiangjiayan.entity.Book;
/**
* T代表你要对哪个实体类对应表进行分页查询
* @author jiangjiayan
*
*/
public class BaseDao<T> {
/**
*
* @param sql 查询不同的实体类,对应的sql不同,所以需要传递
* @param clz 生产出不同的实体类对应实例,然后装进list容器中返回
* @param pageBean 决定是否分页
* @return
* @throws SQLException
* @throws IllegalAccessException
* @throws InstantiationException
*/
public List<T> executeQuery(String sql,Class clz,PageBean pageBean) throws SQLException, InstantiationException, IllegalAccessException{
Connection con=DBAccess.getConnection();
PreparedStatement ps = null;
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.getLong(1)+"");
}
//查询符合条件的结果
String pageSql=getPageSql(sql,pageBean);
ps=con.prepareStatement(pageSql);
rs=ps.executeQuery();
}else {
ps=con.prepareStatement(sql);
rs=ps.executeQuery();
}
List<T> ls=new ArrayList<>();
T t;
while(rs.next()) {
/**
* 1、实例化book对象(该对象是空的,但不为null)
* 2、取book的所有属性,然后给其赋值
* 2.1、获取所有属性对象
* 2.2、给属性对象赋值
* 3、赋值完的book对象装进list容器中
*
*/
//ls.add(new Book(rs.getInt("bid"), rs.getString("bname"), rs.getFloat("price")));
t = (T)clz.newInstance();
Field[] fild = clz.getDeclaredFields();
for(Field fl:fild) {
fl.setAccessible(true);
fl.set(t, rs.getObject(fl.getName()));
}
ls.add(t);
}
DBAccess.close(con, ps, rs);
return ls;
}
/**
* 利用原生sql拼接出符合条件的结果集的查询sql
* @param sql
* @param pageBean
* @return
*/
private String getPageSql(String sql, PageBean pageBean) {
// TODO Auto-generated method stub
return sql+" limit "+pageBean.getStartIndex()+","+pageBean.getRows();
}
/**
* 获取符合条件的总记录数的sql通用语句
* @param sql
* @return
*/
private String getCountSql(String sql) {
// TODO Auto-generated method stub
return "select count(*) from ("+sql+") t1 ";
}
/**
*
* @param k book
* @param sql
* @param attrs bid,bname,price
* @return
* @throws SQLException
* @throws SecurityException
* @throws NoSuchFieldException
* @throws IllegalAccessException
* @throws IllegalArgumentException
*/
public int executeUpdate(String sql,T t,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;
for (String attr : attrs) {
f = t.getClass().getDeclaredField(attr);
f.setAccessible(true);
ps.setObject(loop++, f.get(t));
}
int n=ps.executeUpdate();
DBAccess.close(con, ps, null);
return n;
}
}