前言:依稀记得自己学MVC的时候,找了好多书,也问了我表哥,也找了好多文章。虽然知道了大概怎么回事,但是自己一来没做笔记,二来也没有什么经验,三来也没有怎么深入的打代码,一直都不知道MVC到底怎么回事,代码究竟怎么写。于是,今天就根据自己的经验写了这篇文章,如果文章介绍有错,欢迎各位指出。
模型(Model)封装着数据源和这些数据的业务操作。
视图(View)代表用户交互页面。它可以传递用户请求到控制器中,也可以获取模型传递过来的数据,并将这些数据插入到页面中展现给用户。
控制器(Contaoller)负责对视图传递过来的请求进行解析,并通过调用模型中的方法获取数据传递给视图。
在独立运行的GUI客户端,用户要求可能是一些鼠标单击或是菜单选择操作。在Web应用程序中,他们的表现形式可能是一些来自客户端的GET或POST的HTTP请求。模型所实现的行为包括处理业务和修改模型的状态。根据用户要求和模型行为的结果,控制器选择一个视图作为对用户请求的应答。通常一组相关功能集对应一个控制器。如下图所示为MVC三个组件之间的关系图。
我们可以列举一个例子:自己进入了一家饭店,叫来了老板表示自己要点菜,老板看你不是乞丐,于是很高兴的为你服务。点完菜之后,老板将菜单传递给会做这些菜的厨师,厨师一看就将这些菜的材料都准备好之后开始下锅炒了起来。当菜做好之后,厨师叫来了老板,老板端着做好的菜便向你所坐的位置走了过来,并且将所做好的饭菜呈现你的面前。
在这个案例中,老板对应控制器,厨师对应模型,饭菜对应视图。老板有权对你进行身份验证,确定你没问题之后,老板将你的需求记录下来并传递给可以做这些菜的厨师。厨师结果老板的菜单之后,所准备菜的材料便是数据。厨师可以对这些材料进行任意操作,做好成品之后告诉老板娘可以对客户上菜了。
最典型的MVC就是JSP + Servlet + JavaBean模式。
JavaBean作为模型,既可以作为数据模型来封装业务数据,又可以作为业务逻辑模型来包含应用的业务操作。其中,数据模型用来存储或传递业务数据,而业务逻辑模型接收到控制器传过来的模型更新请求后,执行特定的业务逻辑处理,然后返回相应的执行结果。
JSP作为表现层,负责提供页面为用户展示数据,提供相应的表单(Form)来用于用户的请求,并在适当的时候(点击按钮)向控制器发出请求来请求模型进行更新。
Serlvet作为控制器,用来接收用户提交的请求,然后获取请求中的数据,将之转换为业务模型需要的数据模型,然后调用业务模型相应的业务方法进行更新,同时根据业务执行结果来选择要返回的视图。
接下来,让我们们来看看JSP + Servlet + JavaBean的具体案例。这个项目主要是用来获取用户数据,项目的结构大致如此
注意:个人不喜欢使用接口,所以写到一半就没写了,下面放出的代码也是没有的 0.0
项目的代码按照【表现层】 --- 【模型对象】--- 【数据访问】 --- 【业务处理】的思路来写的。因为个人觉得,首先要有内容,有哪些东西(HTML元素)可以操作。这些东西操作的对象是谁,能够干嘛(增删改查)。这些都知道了之后,就知道业务处理该怎么写了。
好了,第一步:先创建页面。
<a href="find?findStyle=findAall">查询所有用户</a>
<a href="find?findStyle=find&name=张三">查询张三</a>
<a href="find?findStyle=find&name=李四">查询李四</a>
<a href="find?findStyle=find&name=王五">查询王五</a>
<table border="1" cellspacing="0" cellpadding="10">
<tr>
<th>ID编号</th>
<th>姓名</th>
<th>性别</th>
<th>年龄</th>
<th>手机号码</th>
<th>QQ</th>
<th>邮箱</th>
</tr>
<c:forEach var="user" items="${userObj}">
<tr>
<td>${user.getId()}</td>
<td>${user.getName()}</td>
<td>${user.getSex()}</td>
<td>${user.getAge()}</td>
<td>${user.getPhone()}</td>
<td>${user.getQq()}</td>
<td>${user.getEmail()}</td>
</tr>
</c:forEach>
</table>
主要思路就是,通过超链接去访问Controller,最后Controller返回结果时跳转到该页面,然后将数据插入到index页面中返回到客户端渲染出来。
第二步:创建MOD对象 User.java
private int id; //用户ID
private String name; //姓名
private int sex; //性别
private int age; //年龄
private long phone; //手机号码
private int qq; //QQ
private String email; //邮箱
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getSex() {
return sex;
}
public void setSex(int sex) {
this.sex = sex;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public long getPhone() {
return phone;
}
public void setPhone(long phone) {
this.phone = phone;
}
public int getQq() {
return qq;
}
public void setQq(int qq) {
this.qq = qq;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
第三步:创建JDBC数据访问类DataBase.java和UserDaoImp.java
//数据库连接
public class BaseDao {
private static final String Drive="com.mysql.jdbc.Driver";
private static final String DBUrl="jdbc:mysql://localhost:3306/user_msg";
private static final String DBUser = "root";
private static final String DBPassword = "root0503";
protected Connection con;
protected PreparedStatement ps;
protected ResultSet rs;
//1、获取数据库连接
public Connection getConnection(){
try{
Class.forName(Drive);
con = DriverManager.getConnection(DBUrl, DBUser, DBPassword);
}catch(ClassNotFoundException e){
e.printStackTrace();
}catch(SQLException e){
e.printStackTrace();
}
return con;
}
//2、关闭数据库相关对象
public static void closeAll(ResultSet rs,Statement ps,Connection con){
try{
if(rs != null){
rs.close();
}
if(ps != null){
ps.close();
}
if(con != null){
con.close();
}
}catch(SQLException e){
e.printStackTrace();
}
}
}
//UserDaoImpl类
public class UserDaoImpl extends BaseDao implements IUserDao{
public List<User> find(String name) {
List<User> list = new ArrayList<User>();
String sql = "select * from users where name = ?";
con = super.getConnection();
try{
ps = super.getConnection().prepareStatement(sql);
ps.setString(1, name);
super.rs = ps.executeQuery();
if(rs.next()){
User user = new User();
user.setId(rs.getInt("id"));
user.setName(rs.getString("name"));
user.setSex(rs.getInt("sex"));
user.setAge(rs.getInt("age"));
user.setPhone(rs.getLong("phone"));
user.setQq(rs.getInt("qq"));
user.setEmail(rs.getString("email"));
list.add(user);
}
}catch(Exception e) {
throw new RuntimeException(e);
}finally{
super.closeAll(rs, ps, con);
}
return list;
}
public List<User> findAll() {
List<User> list = new ArrayList<User>();
String sql = "select * from users";
con = super.getConnection();
try{
ps = super.getConnection().prepareStatement(sql);
super.rs = ps.executeQuery();
while(rs.next()){
User user = new User();
user.setId(rs.getInt("id"));
user.setName(rs.getString("name"));
user.setSex(rs.getInt("sex"));
user.setAge(rs.getInt("age"));
user.setPhone(rs.getLong("phone"));
user.setQq(rs.getInt("qq"));
user.setEmail(rs.getString("email"));
list.add(user);
}
}catch(Exception e) {
throw new RuntimeException(e);
}finally{
super.closeAll(rs, ps, con);
}
return list;
}
}
哈哈,这一步我是看书刚学的。以前我直接导入DataBase类,或者直接调用,这一次是通过extends继承了DataBase类,然后通过super来调用父类的方法和属性,这一步绝了,这样就不用老是调用来调用去了。
第四部:业务处理Servlet类UserOpra.java
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//设置请求报文中的编码方式(放在提取前)
request.setCharacterEncoding("utf-8");
//设置响应报文中的编码方式(放在输出前)
response.setContentType("text/html;charset=utf-8");
String findStyle = request.getParameter("findStyle");
UserDaoImpl udi = new UserDaoImpl();
List<User> user = null;
if(findStyle.equals("findAall")){
System.out.println("查询所有用户的信息");
user = udi.findAll();
}else{
String name = request.getParameter("name");
System.out.println("查询"+name+"的信息");
user = udi.find(name);
}
request.getRequestDispatcher("index.jsp").forward(request, response);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request,response);
}
好了,代码都写玩了,现在运行代码,看看实际效果
PS:我已经挺久没写过后端了,在写案例代码的时候我发现我不会写了......如果有错误,希望各位踊跃的说出来。