zoukankan      html  css  js  c++  java
  • 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(属性名)。

    清醒时做事,糊涂时读书,大怒时睡觉,独处时思考; 做一个幸福的人,读书,旅行,努力工作,关心身体和心情,成为最好的自己 -- 共勉
  • 相关阅读:
    python 3.8获取当前时间
    .Net Core WebApi 添加Swagger和Redis缓存
    缓存一【微软自带的类库System.Web.Caching】
    rabbitMQ安装运行
    layui添加阿里巴巴图标库
    github无法访问,链接超时解决办法
    Layui + zTree注意事项
    EFCore CodeFirst需要引用的包
    python练习题【杭州多测师】【杭州多测师_王sir】
    mysql数据库题目【多测师_王sir】【杭州多测师】
  • 原文地址:https://www.cnblogs.com/hello-yz/p/5445699.html
Copyright © 2011-2022 走看看