java oop第10章_JDBC03(MVC分层模式)

引言:在进行程序开发的时候,为了更加利于程序的管理我们引入了新的开发模式MVC分层模式,即按功能将程序代码分别分为M(Model模型)、V(View视图)、C(Controller控制器)三个组成部分。

 

 

 

一、      MVC各层的详解:

  1. 1.    M(Model)模型层:

      提供一些基础数据给控制器进行调用,完成服务器端数据的管理,其中又分成如下几个部分:

        1)    Entity实体:实体中的属性与数据库的字段对应,通过实体的属性就可以携带数据与数据表建立联系。

package com.oop.entity;

import java.io.Serializable;

/**
 * 用户实体
 *
 */
public class User implements Serializable {
    private static final long serialVersionUID = 1L;
    
    private Integer userId;        //用户编号
    private String userName;    //用户名
    private String mobile;        //电话号码
    private String email;        //电子邮箱
    private String passWord;    //密码
    
    public Integer getUserId() {
        return userId;
    }
    public void setUserId(Integer userId) {
        this.userId = userId;
    }
    public String getUserName() {
        return userName;
    }
    public void setUserName(String userName) {
        this.userName = userName;
    }
    public String getMobile() {
        return mobile;
    }
    public void setMobile(String mobile) {
        this.mobile = mobile;
    }
    public String getEmail() {
        return email;
    }
    public void setEmail(String email) {
        this.email = email;
    }
    public String getPassWord() {
        return passWord;
    }
    public void setPassWord(String password) {
        this.passWord = password;
    }
    
    
    public User() {
         
    }
    
    public User(Integer userId) {
        this.userId = userId;
    }
    public User(Integer userId, String userName, String mobile, String email, String password) {
        this.userId = userId;
        this.userName = userName;
        this.mobile = mobile;
        this.email = email;
        this.passWord = password;
    }
    public User(String userName, String mobile, String email, String password) {
        this.userName = userName;
        this.mobile = mobile;
        this.email = email;
        this.passWord = password;
    }
    
    /**
     * toString()方法
     */
    @Override
    public String toString() {
        return "User [userId=" + userId + ", userName=" + userName + ", mobile=" + mobile + ", email=" + email
                + ", password=" + passWord + "]";
    }
    
}

        2)    DAO(data access object)数据访问对象:提供一些CRUD的方法(将被service调用),实现操作数据的目的。

package com.oop.dao.impl;

import com.oop.dao.UserDao;
import com.oop.entity.User;
import com.oop.util.BaseDao;

/**
 * 管理“用户”Dao的实现类
 */
public class UserDaoImpl extends BaseDao implements UserDao {
    User userr  =  null;
    
    public User selectUserByUP(User user) {
        try {
            ct = getConnection();
            String sql = "SELECT * FROM tb_user WHERE username = ? AND password = ?";
            pst = ct.prepareStatement(sql);
            pst.setString(1, user.getUserName());
            pst.setString(2, user.getPassWord());
            rs = pst.executeQuery();
            while (rs.next()) {
                userr  = new User();
                userr.setUserId(rs.getInt("user_id"));
                userr.setUserName(rs.getString("username"));
                userr.setMobile(rs.getString("mobile"));
                userr.setPassWord(rs.getString("password"));
                userr.setEmail(rs.getString("email"));
                
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            closeAll();
        }

        return userr;
    }
}

        3)    Service业务层:完成一些DAO、Controller不能或不方便处理的任务,他也会提供一些方法给Controller调用。

扫描二维码关注公众号,回复: 7691588 查看本文章
package com.oop.service.impl;


import com.oop.dao.UserDao;
import com.oop.dao.impl.UserDaoImpl;
import com.oop.entity.User;
import com.oop.service.UserService;
/**
 * 管理“用户”的service实现类
 * @author zhangzimu
 *
 */
public class UserServiceImpl implements UserService {

    UserDao userDao = new UserDaoImpl();
    /**
     * 通过用户名、密码查询用户对象的service层方法
     * 当前的登录功能对应service层只需要调用DAO层的方法,并将结果返回给Controller即可,不需要处理额外的数据
     * @param user:是user类型的对象,其中携带username和password,最终传到DAO层作为查询的条件。
     * @return:返回通过username和password查询到的user对象。
     */
    @Override
    public User findUserByUP(User user) {
        
        return userDao.selectUserByUP(user);
    }

}
  1. 2.    C(Controller)控制器:

      其作用主要是实现“准备数据”、“控制跳转”。准备数据通常有两种途径获取需要准备的数据(从请求中获取、从查询数据库获取);控制跳转通常有两种方式(转发、重定向)。

package com.oop.controller;

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import com.oop.entity.User;
import com.oop.service.UserService;
import com.oop.service.impl.UserServiceImpl;

/**
 * 控制器:用于接收“登录”请求的控制器
 * 当在login.jsp页面中发送/loginServlet请求时是以post方式提交时就会自动调用doPost()方法;
 */
public class LoginServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;

    // 实例化UserServiceImpl的对象
    UserService userService = new UserServiceImpl();

    public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        // 设置字符编码
        request.setCharacterEncoding("UTF-8");
        response.setCharacterEncoding("UTF-8");
        response.setContentType("text/html;charset=UTF-8");

        /*
         * 1)从请求中获取“用户名”、“密码”。 request.getParameter("username"):
         * 获取input的name为username这个输入框中的value值 (用户输入的“用户名称”) value = "admin"
         */

        String username = request.getParameter("username");
        String password = request.getParameter("password");
        // 创建一个User类型的对象,将以上获取到的数据通过调用setXXX()方法为属性赋值。通过对象就可以传递属性值
        User user = new User();
        user.setUserName(username);
        user.setPassWord(password);

        /* 2)调用service层的方法,service又调用Dao层的方法,查询数据库获取User类型的对象。 */
        User loginUser = userService.findUserByUP(user);

        // 3)根据以上的查询结果判断用户是否合法,若合法跳转到成功页面(/success.jsp);
        // 若不合法跳转到登录页面(/login.jsp),同时提供错误消息。

        if (loginUser != null) {
            // 合法跳转到成功页面(/success.jsp),同时显示成功消息
            
            // 键值对,通过键值对就可以在目标jsp页面(success.jsp)中使用EL表达式调用(   欢迎您:${loginUser.getUserName()}),在网页中显示数据,达到不会显示Java代码的目的
            request.setAttribute("loginUser", loginUser);
            //将请求转发到目标页面,
            request.getRequestDispatcher("/success.jsp").forward(request, response);

        } else {
            // 不合法跳转到登录页面(/login.jsp),同时提供错误消息。

            /**
             * 第一种跳转:request.getRequestDispatcher().forward(request, response);
             * 1、属于服务器跳转,相当于方法调用,在执行当前文件的过程中转向执行的目标文件,两个文件(当前文件和目标文件)属于同一次请求,前后页共用一个request,
             * 可以通过此来传递一些数据或者会话(session)信息。request.setAttribute()和request.getAttribute()。
             * 2、在前后两次执行后,地址栏不变,仍是当前文件地址。
             * 3、不能转向本web应用之外的页面和网站,所以转向的速度要快。
             * 4、URL中所包含的“/”表示应用程序(项目webroot)的路径
             */
            request.setAttribute("errorInfo", "用户名或密码错误");
            request.getRequestDispatcher("/login.jsp").forward(request, response);
            
            /**
             * 第二种跳转:response.sendRedirect()。
             * 1、属于重定向,也是客户端跳转,相当于客户端向服务端发送请求之后,服务器返回一个响应,客户端接收到响应之后又向服务端发送一次请求,一共是2次请求,
             *     前后页不共用一个request,不能读取转向前通过request.setAttribute()设置的属性值。
             * 2、在前后两次执行后,地址栏发生改变,是目标文件的地址。
             * 3、可以转向到本web应用之外的页面和网站,所以转向的速度相对要慢。
             * 4、URL种所包含的"/"表示根目录的路径
             * 
             */
            
            /**
             * 特殊的应用:对数据进行修改、删除、添加操作的时候,应该用response.sendRedirect()。
             * 如果是采用了request.getRequestDispatcher().forward(request,response),
             * 那么操作前后的地址栏都不会发生改变,仍然是修改的控制器,如果此时再对当前页面刷新的话,
             * 就会重新发送一次请求对数据进行修改,这也就是有的人在刷新一次页面就增加一条数据的原因。
             * 如何采用第二种方式传递数据:
                1、可以选择session,但要在第二个文件中删除;
                2、可以在请求的url中带上参数,如"add.htm?id=122"
             */

        }

    }

}
  1. 3.    V(view)视图:

      给用户展示数据的平台,通常是由JSP(Java sever page)作为视图。

      JSP可以完全兼容HTML的内容,又增加了一些动态处理数据的功能。

login.jsp

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <base href="<%=basePath%>">
    
    <title>My JSP 'login.jsp' starting page</title>
    
    <meta http-equiv="pragma" content="no-cache">
    <meta http-equiv="cache-control" content="no-cache">
    <meta http-equiv="expires" content="0">    
    <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
    <meta http-equiv="description" content="This is my page">
    <!--
    <link rel="stylesheet" type="text/css" href="styles.css">
    -->

  </head>
  
  <body>
  <!--action="/loginServlet":指定请求提交的路径。
          method = "post":指定提交的方式
   -->
   <p>${pageContext.request.contextPath}表示JSP取得绝对路径的方法,也就是取出部署的应用程序名或者是当前的项目名称<p/>
   <p>会在web xml文件中去找<p/>
   
      <form action="${pageContext.request.contextPath}/loginServlet" method = "post">
          用户名称:<input type = "text" name = "username" /><br/><br/>
          用户密码:<input type = "password" name = "password"/><br/><br/>
          ${errorInfo}<br/>
          <input type = "submit" value = "提交"/>&nbsp;&nbsp;&nbsp;
          <input type = "reset" value = "重置"/><br/><br/>
      </form>
  </body>
</html>

success.jsp

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <base href="<%=basePath%>">
    
    <title>My JSP 'success.jsp' starting page</title>
    
    <meta http-equiv="pragma" content="no-cache">
    <meta http-equiv="cache-control" content="no-cache">
    <meta http-equiv="expires" content="0">    
    <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
    <meta http-equiv="description" content="This is my page">
    <!--
    <link rel="stylesheet" type="text/css" href="styles.css">
    -->

  </head>
  
  <body>
   欢迎您:${loginUser.getUserName()}
  </body>
</html>

 

二、      MVC各层之间调用的注意事项:

  1、      上一层调用下一层:如Controller调用Service,Service调用Dao,不允许反向调用。

  2、      同一层之间:尽量避免同层之间调用。

 

三、      MVC分层模式下的案例:

案例描述:实现登录功能------------------------------------------------------------案例代码在上面

  1、      创建一个web project:MVC

  2、      加入MySQL的jar包:

  3、      创建项目需要的包:按照MVC分层模式来创建包。

  4、      编写登录页面:/login.jsp

      表单中提供“用户名输入框”、“密码输入框”、“登录按钮”

      当点击“登录按钮”时就会向服务器发送登录请求

      请求路径: /loginServlet

      请求参数:参数名为usernamepassword

  5、      编写Controller:

    Com.oop.controller.LoginServlet

   1)      从请求中获取“用户名”、“密码”。

   2)      调用service层的方法,service又调用Dao层的方法,查询数据库获取User类型的对象。

      3)      根据以上的查询结果判断用户是否合法,若合法跳转到成功页面(/success.jsp);若不合法跳转到登录页面(/login.jsp),同时提供错误消息。

 

6、      处理视图:/login.jsp、/success.jsp

  /login.jsp:显示错误消息

  /success.jsp:显示成功消息

 

 

猜你喜欢

转载自www.cnblogs.com/zhangzimuzjq/p/11768480.html