MVC思想
M:model 模型
V:view 视图
C:control 控制器
用户(客户端或浏览器)向服务端发送请求,控制器(control)接收请求,并进行处理,选择对应的模型(model),模型(model)与数据库进行数据交互等操作,交互完成后,模型(model)将数据发送到控制器(control),控制器(model)进行处理,选择相应的视图(view)来展示这些数据,并呈现到浏览器上,形成最终的显示页面。
使用MVC的思想,结合servlet和jsp进行数据库的查询操作
1.实体类Hero
实体类Hero是一个由普通Java代码编写的类
将其实例化为对象后,可调用其内部编写的各种方法实现与数据库之间的交互操作
其代码如下:
package bean;
public class Hero {
// 定义数据库中表的字段名
//成员变量
public int id;
public String name;
public float hp;
public int damage;
//这个方法的作用是获取数据库中表的 字段为id 的数据
public int getId() {
return id;
}
//这个方法的作用是设置表中字段为id 的数据
public void setId(int id) {
this.id = id;
}
//获取字段名为name的数据
public String getName() {
return name;
}
//设置字段名为name的数据
public void setName(String name) {
this.name = name;
}
//获取字段名为hp的数据
public float getHp() {
return hp;
}
//设置字段名为 hp 的数据
public void setHp(float hp) {
this.hp = hp;
}
//获取字段名为damage的数据
public int getDamage() {
return damage;
}
设置字段名为damage的数据
public void setDamage(int damage) {
this.damage = damage;
}
}
2.HeroDAO
package dao;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;
import bean.Hero; // 导入了编写的 实体类 Hero
public class HeroDAO {
//HeroDAO类的构造方法,
public HeroDAO() {
//创建驱动程序
try {
Class.forName("com.mysql.jdbc.Driver");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
//方法名是getConnection() 返回类型是Connection
public Connection getConnection() throws SQLException {
return DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/db_database24", "root", "914717"); //连接数据库
}
//获取表中一共有多少数据的方法
public int getTotal() {
int total = 0;
//进行数据库连接
try (Connection c = getConnection(); Statement s = c.createStatement();) {
//编写sql语句
String sql = "select count(*) from hero";
//执行查询语句,并返回结果集合
ResultSet rs = s.executeQuery(sql);
while (rs.next()) {
total = rs.getInt(1);//获取第一个字段 id
//每个next是指向的下一个元组,该语句获取的是这个元组的 第一个字段 id 的值
}
System.out.println("total:" + total); //输出最后total的值,就代表表中一共有多少条数据
} catch (SQLException e) {
e.printStackTrace();
}
return total; //返回结果
}
//向数据库表中添加数据
//传入参数为Hero类实例化的hero对象
public void add(Hero hero) {
//编写sql语句
String sql = "insert into hero values(null,?,?,?)";
//连接数据库
try (Connection c = getConnection(); PreparedStatement ps = c.prepareStatement(sql);) {
ps.setString(1, hero.name);
ps.setFloat(2, hero.hp);
ps.setInt(3, hero.damage);
ps.execute();
ResultSet rs = ps.getGeneratedKeys();
if (rs.next()) {
int id = rs.getInt(1);
hero.id = id;
}
} catch (SQLException e) {
e.printStackTrace();
}
}
//修改数据库表中的数据
public void update(Hero hero) {
//编写sql语句
String sql = "update hero set name= ?, hp = ? , damage = ? where id = ?";
//连接数据库
try (Connection c = getConnection(); PreparedStatement ps = c.prepareStatement(sql);) {
ps.setString(1, hero.name);
ps.setFloat(2, hero.hp);
ps.setInt(3, hero.damage);
ps.setInt(4, hero.id);
ps.execute();
} catch (SQLException e) {
e.printStackTrace();
}
}
//修改数据库表中的数据
public void delete(int id) {
//连接数据库
try (Connection c = getConnection(); Statement s = c.createStatement();) {
//编写sql语句
String sql = "delete from hero where id = " + id;
s.execute(sql);
} catch (SQLException e) {
e.printStackTrace();
}
}
//方法名为 get(),返回类型为Hero
public Hero get(int id) {
//实例化对象为空
Hero hero = null;
//连接数据库
try (Connection c = getConnection(); Statement s = c.createStatement();) {
//编写sql语句
String sql = "select * from hero where id = " + id;
//执行查询语句
ResultSet rs = s.executeQuery(sql);
if (rs.next()) {
//将表中的数据都赋值给hero对象
hero = new Hero();
String name = rs.getString(2);
float hp = rs.getFloat("hp");
int damage = rs.getInt(4);
hero.name = name;
hero.hp = hp;
hero.damage = damage;
hero.id = id;
}
} catch (SQLException e) {
e.printStackTrace();
}
return hero;
}
//返回类型为List<Hero> 方法名为list
public List<Hero> list() {
return list(0, Short.MAX_VALUE);
}
public List<Hero> list(int start, int count) {
List<Hero> heros = new ArrayList<Hero>();
//编写sql语句
String sql = "select * from hero order by id desc limit ?,? ";
//连接数据库
try (Connection c = getConnection(); PreparedStatement ps = c.prepareStatement(sql);) {
ps.setInt(1, start);
ps.setInt(2, count);
ResultSet rs = ps.executeQuery();
while (rs.next()) {
Hero hero = new Hero();
int id = rs.getInt(1);
String name = rs.getString(2);
float hp = rs.getFloat("hp");
int damage = rs.getInt(4);
hero.id = id;
hero.name = name;
hero.hp = hp;
hero.damage = damage;
//将hero对象添加到列表中去
heros.add(hero);
}
} catch (SQLException e) {
e.printStackTrace();
}
return heros;
}
}
3.HeroListServlet
这是一个Servlet文件
package servlet;
import java.io.IOException;
import java.util.List;
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 bean.Hero;
import dao.HeroDAO;
/**
* Servlet implementation class HeroListServlet
*/
@WebServlet("/HeroListServlet")
public class HeroListServlet extends HttpServlet {
protected void service(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
List<Hero> heros = new HeroDAO().list();
//设置属性
request.setAttribute("heros", heros);
//呈现视图的页面
request.getRequestDispatcher("listhero.jsp").forward(request, response);
}
}
4.listHero.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8" import="java.util.*"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<table align='center' border='1' cellspacing='0'>
<tr>
<td>id</td>
<td>name</td>
<td>hp</td>
<td>damage</td>
<td>edit</td>
<td>delete</td>
</tr>
<c:forEach items="${heros}" var="hero" varStatus="st">
<tr>
<td>${hero.id}</td>
<td>${hero.name}</td>
<td>${hero.hp}</td>
<td>${hero.damage}</td>
<td><a href="editHero?id=${hero.id}">edit</a></td>
<td><a href="deleteHero?id=${hero.id}">delete</a></td>
</tr>
</c:forEach>
</table>
运行HeroListServlet,结果为
分析查询过程中的MVC(以下观点仅为个人看法)
下面来分析一下这个过程中的MVC分别是什么:
M(模型):模型是用来与数据库进行交互操作(增、删、改、查)的,那上述文件中,发挥此作用的是HeroDAO,HeroDAO在其内部封装了与数据库进行交互操作的方法
V(视图):视图是用来在浏览器中展示的,在上述文件中,listHero发挥了这种作用,在浏览器上呈现最终的数据
C(控制器):控制器是用来处理请求的,将模型与视图连接在一起的,上述文件中HeroListServlet就发挥了这种作用。
以MVC思想实现数据的增删改
接下来我们在上述步骤的基础上完成对数据的增、删、改,并将其显示在页面上。
那我们就要分类好谁是M、谁是V、谁是C;
V的话很简单,就是jsp文件,我们用上面查询所用的代码就可以;
M的话就是与数据库进行交互的HeroDAO;
C的话应该有多个,用户每发起一次请求,网址就会改变一次,所以我认为接收请求的控制器也应该有多种,一种网址对应一种控制器同时对应一种请求。
1.视图(view)的建立:
建立listHero.jsp文件,复制上面文件代码。
首先要构思好整个页面 该怎么实现其各自的功能
比如说 增添数据该怎么增添 , 删除数据该怎么删除 ,修改数据该怎么修改
我们目前展现的页面是这样的
现在将进行如下思考:
怎么增添数据呢?
我们可以在页面设置一个输入框,用于输入数据,然后当我们输入数据并提交之后,这些输入的数据会添加到数据表中并在页面显示出来
怎么删除数据呢?
我们可以点击delete,使该行数据在数据表中删除,并且在页面上显示出来
怎么修改数据呢?
我们点击edit,并输入修改后的值,使数据表里的数据发生改变,并在页面上显示出来
于是我们可以书写如下代码
<%@ page language="java" import="java.sql.*"
contentType="text/html; charset=utf-8" pageEncoding="utf-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<table align='center' border='1' cellspacing='0'>
<tr>
<td>id</td>
<td>name</td>
<td>hp</td>
<td>edit</td>
<td>delete</td>
</tr>
<c:forEach items="${heros}" var="hero" varStatus="st">
<tr>
<td>${hero.id}</td>
<td>${hero.name}</td>
<td>${hero.hp}</td>
//a标签的路径已经给出,所以我们可以想到要建立editHero和deleteHero两个servlet文件
<td><a href="editHero?id=${hero.id}">edit</a></td>
<td><a href="deleteHero?id=${hero.id}">delete</a></td>
</tr>
</c:forEach>
</table>
// 该部分用于用户输入要增加的数据
<div style="margin: 50px auto; width: 300px">
<form action="addHero" method=""post">
name: <input name="name"> <br>
<br> hp: <input
name="hp"> <br> <input type="submit" value="提交">
</form>
</div>
</body>
</html>
这样网页的显示页面就完成了,下面该完成各部分功能的实现
2.控制器(controller)的建立
视图建立完成后,就建立各种控制器。由于我们只有一个视图,所以我们可以把各种控制器最后要显示的页面弄成同一个。
简单来说就是 不同的控制器接收请求 调用模型与数据库进行不同的交互操作后 选择同一个视图展现在浏览器上
以删除数据为例:
当我们点击delete时,就发送了一次请求,页面跳转到deleleHero的Servlet文件中,
在这个文件中,我们接收这次请求的id参数,并且调用HeroDAO文件中的delete()方法,与数据库进行交互操作,删除这一个元组,
最后选择视图,返回到最初显示的页面。
要返回到最初显示的页面,我们可以回退到最初的网址。
因为HeroListServlet是查询操作,所以我们每个控制器最后返回的网址都可以是它的网址,相当于完成数据增删改操作后,对数据表进行了一次查询,并显示在jsp页面上。
清楚之后,开始建立各种控制器;
创建deleteHero
代码如下:
package servlet;
import java.io.IOException;
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 dao.HeroDAO;
/**
* Servlet implementation class deleteHero
*/
@WebServlet("/deleteHero")
public class deleteHero extends HttpServlet {
public void service(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
// 获取网址的参数 id
int id = Integer.parseInt(request.getParameter("id"));
// 建一个HeroDAO对象,目的是完成与数据库的交互操作,在这个文件中是完成数据的删除操作
HeroDAO hero = new HeroDAO();
// 删除这个元组
hero.delete(id);
//响应到HeroListServlet 这个网址,相当于重新进入
response.sendRedirect("HeroListServlet");
}
}
显示效果如下:
创建addHero
代码如下:
package servlet;
import java.io.IOException;
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 bean.Hero;
import dao.HeroDAO;
/**
* Servlet implementation class addHero
*/
@WebServlet("/addHero")
public class addHero extends HttpServlet {
public void service(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
//首先接收显示页面输入框中 用户输入的值
String name = request.getParameter("name");
String hp = request.getParameter("hp");
// 创建一个Hero对象
Hero hero = new Hero();
hero.name = name;
hero.hp = Float.parseFloat(hp);
//此时的hero是一个全新的Hero对象
//实例化HeroDAO
HeroDAO heros = new HeroDAO();
//与数据库进行交互
//调用add()方法,将hero对象加入其中
heros.add(hero);
//响应到初始页面
response.sendRedirect("HeroListServlet");
}
}
显示效果如下:
创建editHero
在修改数据时,我们发现这并不能向增删那样只通过一个文件就可以达到效果
因为我们
1.要选出要修改的元组
2.并输入他们修改后的值
3.之后要修改数据 并显示到页面上
所以这样就要建立三个文件
第一个文件editHero用于 取出要修改的元组
第二个文件editHero.jsp文件用于展示输入框并接收用户输入的数据
第三个文件updateHero文件用于接收修改的值,并对数据进行修改
接下来代码如下:
editHero文件中:
package servlet;
import java.io.IOException;
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 bean.Hero;
import dao.HeroDAO;
/**
* Servlet implementation class editHero
*/
@WebServlet("/editHero")
public class editHero extends HttpServlet {
public void service(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
//获取要修改的 id 元组
int id = Integer.parseInt(request.getParameter("id"));
//先创建一个Hero对象,并把id为‘id’的那一行元组取出来,这样才能进行修改
Hero hero = new HeroDAO().get(id);
//把这个hero对象作为参数传出去
request.setAttribute("hero", hero);
//将参数对象发送到editHero.jsp文件中
request.getRequestDispatcher("editHero.jsp").forward(request, response);
}
}
editHero.jsp文件中:
<%@ page language="java" import="java.sql.*" contentType="text/html; charset=utf-8"
pageEncoding="utf-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<div style="margin:50px auto; width:300px">
<form action="updateHero" method=""post">
//存储用户输入的数据
name: <input name="name" > <br><br>
hp: <input name="hp" >
<br>
//用于存储要修改的元组的id,并进行提交
<input type="hidden" name = "id" value="${hero.id}">
<input type="submit" value="提交">
</form>
</div>
</body>
</html>
updateHero文件中:
package servlet;
import java.io.IOException;
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 bean.Hero;
import dao.HeroDAO;
/**
* Servlet implementation class updateHero
*/
@WebServlet("/updateHero")
public class updateHero extends HttpServlet {
public void service(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
//接收要修改的元组的id ,修改后的值
String name = request.getParameter("name");
String hp = request.getParameter("hp");
String id = request.getParameter("id");
//创建一个hero对象
Hero hero = new Hero();
//对hero对象进行赋值(修改)
hero.name = name;
hero.hp = Float.parseFloat(hp);
hero.id = Integer.parseInt(id);
HeroDAO heros = new HeroDAO();
//在数据表中实现数据的修改
heros.update(hero);
//响应到初始界面
response.sendRedirect("HeroListServlet");
}
}
显示效果如下:
这样,以MVC思想完成对数据的增删改 就已经完成了。
在进行上述操作的过程中,最后显示的网址是没有发生改变的,但是我们要注意,我们并不仅仅是发出了一次请求,而是发出了多次请求,它们原本的网址是不同的,只是我们让它最后显示的网址是相同的。
小结
MVC是一种思想,目前我的理解还有点肤浅,对本篇文章中的M、V是什么还有点疑惑。
现在有两种想法:
一种是M是HeroDAO,V是各种servlet文件
一种是M是除HerolistServlet之外的各种文件,V是HeroListServlet文件
目前我倾向于第一种,但是还是有点疑惑,因为它对数据的更新是在servlet文件中的,HeroDAO只是提供了方法,有点不太理解。可能这个案例本身的界限不是很明显吧。