Model-View-Controller - 杂谈

经典的B/S结构+MVC模式: 

注意:MVC层次均位于server中。

下面通过一个简单并且具体的例子来体会下这种MVC模式:

--- 功能:查询所有图书;涉及到数据库,JSP,Servlet等

Step 1: 创建数据库表用于存储book信息,插入测试数据(其实该步骤已经规划出javaBean里的各个属性了)

CREATE TABLE books (
    bookid VARCHAR (10) NOT NULL,
    bookname VARCHAR (30),
    author VARCHAR (20),
    price FLOAT,
    publisher VARCHAR (20),
    PRIMARY KEY (bookid)
);

INSERT INTO books VALUES('00001','Java','zhangsan',20,'电子工业');
INSERT INTO books VALUES('00002','JSP','lisi',22,'人民邮电');
INSERT INTO books VALUES('00003','Java EE','wang',30,'人民邮电');

Step 2: 

整个查询过程可以规划为

浏览器借助jsp页面(View)发出请求-->Servlet拦截请求(Controller)-->调用业务逻辑方法(Controller)-->通过JDBC与数据库交互(Model)-->回到Servlet并设置jsp属性(View)-->查询结果展示(View)

下面一个个来说:

1) 浏览器借助jsp页面(View)发出请求

Navigator.jsp

<a href="${pageContext.request.contextPath}/findAllBooks">查看所有图书</a>

2) Servlet拦截请求(Controller)

web.xml

    <servlet>
        <servlet-name>BookList</servlet-name>
        <servlet-class>com.chris.web.servlet.BookListServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>BookList</servlet-name>
        <url-pattern>/findAllBooks</url-pattern>
    </servlet-mapping>

3) 调用业务逻辑方法(Controller)

BookListServlet.java

public class BookListServlet extends HttpServlet{
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        BookQueryService bqs = new BookQueryService();
        Set<Book> bookSet = bqs.findAllBooks();
        req.setAttribute("allBooks",bookSet);
        RequestDispatcher rd = req.getRequestDispatcher("/jsp/books.jsp");
        rd.forward(req,resp);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req,resp);
    }
}

4) 通过JDBC与数据库交互(Model)

BookQueryService.java

public class BookQueryService {

    public Set<Book> findAllBooks() {
        Connection con = BasicJdbcOperation.getConnection();
        String sql = "select * from books";
        Set<Book> bookSet = new HashSet<Book>();
        try {
            PreparedStatement ps = con.prepareStatement(sql);
            ResultSet rs = ps.executeQuery();
            while (rs.next()){
                Book book = new Book();
                book.setBookId(rs.getString(1));
                book.setBookName(rs.getString(2));
                book.setAuthor(rs.getString(3));
                book.setPrice(rs.getFloat(4));
                book.setPublisher(rs.getString(5));
                bookSet.add(book);
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            BasicJbdcOperation.close();
        }
        return bookSet;
    }
}

Book.java (JavaBean)

public class Book {
    private String bookId;
    private String bookName;
    private String author;
    private float price;
    private String publisher;

    public String getBookId() {
        return bookId;
    }

    public void setBookId(String bookId) {
        this.bookId = bookId;
    }

    public String getBookName() {
        return bookName;
    }

    public void setBookName(String bookName) {
        this.bookName = bookName;
    }

    public String getAuthor() {
        return author;
    }

    public void setAuthor(String author) {
        this.author = author;
    }

    public float getPrice() {
        return price;
    }

    public void setPrice(float price) {
        this.price = price;
    }

    public String getPublisher() {
        return publisher;
    }

    public void setPublisher(String publisher) {
        this.publisher = publisher;
    }
}

BasicJdbcOperation.java

public class BasicJdbcOperation {

    private static Connection con;

    public static Connection getConnection(){
        Connection connection = null;
        try {
            Class.forName("com.mysql.jdbc.Driver");
            connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/crud","root", "");
            con = connection;
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return connection;
    }

    public static void close() {
        try {
            if (con != null) {
                con.close();
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        try {
            //加载驱动
            Class.forName("com.mysql.jdbc.Driver");
            //建立数据库连接
            Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/shiro","root", "");
            //创建SQL语句
            String sql = "select * from users where username=? and password=?";
            //创建语句对象
            PreparedStatement ps = connection.prepareStatement(sql);
            //变量赋值,替换?
            ps.setString(1, "Chris");
            ps.setString(2, "123");
            //执行SQL语句
            ResultSet resultSet = ps.executeQuery();
            //处理ResultSet
            while (resultSet.next()){
                System.out.println(resultSet.getString(2));
            }
            //关闭相关对象
            resultSet.close();
            ps.close();
            connection.close();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

}

 5) 回到Servlet并设置jsp属性(View)

回到3) 调用业务逻辑方法(Controller),

        RequestDispatcher rd = req.getRequestDispatcher("/jsp/books.jsp");
        rd.forward(req,resp);

 

Demo下载

 

==============MVC模式小结==============

对于任何Java Web应用,在完全确定需求之后,就需要考虑应用的整体架构。MVC模式提供了设计架构的良性思维方式,也符合项目通常的开发规则。

对于任何一个功能/应用,首先考虑用户怎么用?既然是Java Web应用,必然涉及浏览器,也就需要大量的页面支持,这也就构成了View部分。

那么大量页面之间如何发生关系,如何跳转,也就需要控制器(通常是Servlet),这也构成Controller部分。

页面有了,如何跳转也有了,但是页面里的数据呢?这个就涉及Model部分了,同数据库或者其他数据源交互。

 

View部分:

  1. 用户发送请求方式:超链接href;浏览器地址栏(get);表单提交(post);Ajax请求
  2. 页面展示:采用EL表达式+Jstl,比如输出提示信息${info};输出对象信息${book.bookid}。当前流行的方式还是采用javascript

Model部分:

  1. JavaBean层:包括entity和dto(可能也叫domain, model等),对应于数据库表实体和前端信息实体
  2. Service层:供Controller层调用的业务逻辑
  3. DAO层:数据库CRUD的封装

Controller部分:

通常采用Servlet实现,extends HttpServelt。按以下步骤实现一个控制器:

  1. 获取前端请求信息
  2. 调用Service,并与后台交互
  3. 保存服务器返回数据
  4. 转到响应界面

获取信息
获取请求信息:

request.getParameter(paraname), request.getParameterValues(paraname)
获取session中信息:

session.getAttribute(属性名)
获取Cookie中信息:

request.getCookies()

获取请求头信息 

获取Servlet的配置信息

保存信息:
保存到session中:

session.setAttribute(属性名,要保存的对象),供用户后续的所有访问过程使用。

保存到request中:

request.setAttribute(属性名,要保存的对象),供后续页面使用(页面与当前的Servlet属于同一次请求)

保存到cookie,Cookie cookie = new Cookie("name","value"); response.addCookie(cookie); 供客户端在以后的时间访问。

 

响应:

使用专门的文件进行响应:

方式一:
RequestDispatcher rd = request.getRequestDispatcher(目标文件); 
rd.forward(request,response); // 完成跳转 

方式二:
response.sendRedirect(目标文件);

注意:如果当前功能完成的是对数据库的插入操作,如果用户刷新就会产生错误。要避免错误,不能使用RequestDispatcher,可以使用方式二。如果使用方式二,就不能在当前文件和目标文件之间通过request共享信息了。如果要共享可以用session。使用session的时候,用完一定要删除这个对象session.removeAttribute(属性名)。

posted on 2016-04-29 11:30  -赶鸭子上架-  阅读(319)  评论(0编辑  收藏  举报