Mô hình MVC & Code demo MVC1/ MVC2 với JSP/Servlet/JavaBean

Hi guys, bài trước mình có ý định viết series về Java Core, bắt đầu từ java-core-huong-dan-cai-dat-intellij-va-cau-hinh-moi-truong-java, cơ mà vẫn chưa có thêm bài viết mới nào . . . nay tìm hiểu mô hình MVC, cũng gần như một base knowledge mà chúng mình cần nắm chắc, đặc biệt cho những ai muốn đi sâu về web 😀 Bài viết hôm nay có contents như sau:

  1. Khái quát chung vể kiến trúc model1 & model2 (MVC).
  2. Phân biệt 3 layer vs 3 tier.
  3. Code demo sử dụng JSP/ Servlet/ JavaBean.

1. Khái quát chung về kiến trúc model1 & model2 (MVC) trong java.

  • Mô hình MVC & ưu, nhược điểm.
  • MVC1 ưu, nhược điểm.
  • MVC2 ưu, nhược điểm.
  • Sự khác và giống nhau của MVC1 & MVC2.
1.1.  Mô hình MVC.

MVC (Model – View – Controller) – MVC Pattern Design là một mô hình kiến trúc phần mềm được tạo ra với mục đích quản lí và xây dựng dự án phần mềm có hệ thống hơn, nói cụ thể thì nó là một mẫu thiết kế nhằm chia tách phần giao diện và phần code của ứng dụng để dễ dàng quản lí, bảo trì và phát triển. MVC được áp dụng trên hầu hết các ngôn ngữ lập trình hướng đối tượng hiện nay như C++, C#, Java, PHP, …

MVC chia ứng dụng phần mềm ra thành 3 phần có tương tác với nhau:

  1. Model: thường là các class chứa thông tin đối tượng (dữ liệu), tương tác truy xuất database.
  2. View: là nơi nhận dữ liệu từ model, database và sắp xếp chúng chính xác nhờ yêu cầu từ controller và truyền về client.
  3. Controller: Đóng vai trò trung gian giữa Model và View, nó có nhiệm vụ nhận yêu cầu từ client sau đó xử lý request, load model và gửi data qua view tương ứng với nhau rồi trả kết quả về cho client.

MVC.png

Trên đây đều là lí thuyết, bạn dạo qua 1 vòng google là thấy :D, ví dụ thực tiễn: bạn đi ăn kem Tràng Tiền vào mùa đông ở Hà Nội :3

Bạn vào quầy order kem với người bán hàng thì bạn đóng vài trò là User, yêu cầu của bạn là request gửi đến thanh niên bán hàng, lúc này thanh niên bán kem phải làm ra cây kem, mà muốn làm ra cây kem thì cần nguyên liệu là ốc quế, kem, etc, …chúng nó chính là Model, và não của thanh niên bán kem đóng vai trò là Controller (Quá trính xử lí yêu cầu của người mua kem): nhận order của bạn,  lấy ốc quế, tạo kem, đưa kem, nhận tiền, trả lại tiền, etc,…Cuối cùng, cây kem đến tay bạn đóng vai trò là View. Phần View được làm nên từ những thành phần thông qua Model. 

Giờ hết kem, bạn muốn ăn nữa, thì không thể nhìn vào cái View (kem cũ) mà có kem được mà phải yêu cầu người bán hàng bán, như vậy, chúng ta mua kem hay code theo mô hình MVC thì cũng phải đi đầy đủ từng bước, bạn không thể k order vs người bán hàng mà ngang nhiên lấy kem đi được (trộm cắp đấy :v) hay người bán hàng không thể bán kem cho bạn nếu thiếu đi Model (nguyên liệu làm kem).

Quay trở lại phần kĩ thuật, xử lí chung của web theo mô hình MVC như sau:

  1. User gọi yêu cầu xử lí từ trang chủ.
  2. Controller nhận yêu cầu và đưa lệnh xử lí yêu cầu đó. Các lệnh thực thi với phần View thì cập nhật hoặc phục vụ yêu cầu trang web, với Model thì để biểu đạt logic (Nếu lệnh yêu cầu có logic).
  3. Model thực thi phần logic và lấy cơ sở dữ liệu rồi gửi trả lại phản hồi dựa trên hướng dẫn của Controller.
  4. Controller truyền dữ liệu cho View để cập nhận giao diện hiển thị cho người dùng.

Ưu, nhược điểm của mô hình MVC

Nếu bạn cho rằng chỉ tạo 1 project rất nhỏ mà tốn công phân chia để làm gì, hay còn đang loay hoay và mơ hồ với việc tạo 1 project theo mô hình MVC thì đó chính là nhược điểm của mô hình MVC: Đối với dự án nhỏ việc áp dụng mô hình MVC gây cồng kềnh, tốn thời gian trong quá trình phát triển. Tốn thời gian trung chuyển dữ liệu của các thành phần. Phải có kiến thức vững và chuẩn, để tránh bị nhầm lẫn về các mô hình.

Ngược lại, nếu bạn nắm bắt tốt thì MVC mang lại ưu điểm vô cùng lớn: Thể hiện tính chuyên nghiệp trong lập trình, phân tích thiết kế. Do được chia thành các thành phần độc lập nên giúp phát triển ứng dụng nhanh, đơn giản, dễ nâng cấp, bảo trì..

Người ta chia MVC làm 2 loại là MVC model1 & MVC model2 như sau.

1.2. Mô hình MVC1 – Ưu, nhược điểm.

Capture.PNG

Như bạn thấy trong hình trên là model 1 architecture’s flow:

  1. Trình duyệt gửi yêu cầu cho trang JSP.
  2. JSP truy cập Java Bean và gọi sang business logic.
  3. Java bean kết nối với cơ sở dữ liệu, nhận và lưu dữ liệu.
  4. Response được gửi lại cho user bởi JSP.

Nhược điểm:

  • Navigation control is decentralized  bởi vì mỗi trang đều chứa các logic để xác định trang tiếp theo. Nếu tên trang .JSP được thay đổi mà nó được gọi bởi các trang khác, chúng ta cần phải thay đổi nó trong tất cả các trang dẫn đến vấn đề maintenance (bảo trì).
  • Time consuming Bạn cần phải dành nhiều thời gian để phát triển JSP tags. Vì vậy mà chúng ta không cần phải sử dụng scriptlet tag.
  • Hard to extend Nó khá ổn cho các ứng dụng nhỏ nhưng cho các ứng dụng lớn sẽ có vấn đề.

Ưu điểm: 

  • Dễ dàng và nhanh chóng để phát triển ứng dụng web.
1.3 Mô hình MVC2 – Ưu, nhược điểm.

Capture.PNG

Capture1

  1. Web Browser send request đến server thông qua các control trên form HTML hay JSP, hay query string url hay qua cookies.
  2. Servlet – Controller đón nhận request và xác định Model tương ứng để tạo ra instance của JavaBean để đón nhận các giá trị nhập từ request để lưu trữ và xử lý.
  3. Model thực hiện xử lý, kết nối dữ liệu vật lý dưới DBMS (nếu có) và trả kết quả trả về cho Controller.
  4. Kết quả xử lý được truyền vào Servlet – Controller, Servlet Controller thực hiện tạo hay lựa chọn View để từ đó đưa kết quả xử lý hay dữ liệu lấy từ Model để cập nhật lại trang kết quả View.
  5. Controller gửi View qua  response cho người dùng để browser có thể trình bày dữ liệu trong Web Browser.

Sơ đồ trên khá sáng tỏ về MVC2 architecture rồi, nên không nhiều lời nữa ha 😀

Ưu điểm:

  • Navigation control is centralized Now only controller contains the logic to determine the next page.
  • Easy to maintain.
  • Easy to extend.
  • Easy to test.
  • Better separation of concerns.

Nhược điểm:

Chúng ta cần phải viết controller code. Nếu chúng ta thay đổi controller code thì cần phải recompile lại class và redeploy lại các application.

1.4.  Sự khác, giống nhau, ưu, nhược điểm của MVC1 & MVC2.
  • Trong MVC1, controller và view đều là Jsp. MVC1 là thế hệ đầu tiên sử dụng JSP/ JavaBeans để thực hiện mô hình MVC, yêu cầu từ phía client sẽ được gửi tới trang JSP ban đầu được coi là controller xử lý, sau đó truyền lệnh thực thi đến các JavaBeans, các JavaBeans lấy dữ liệu từ database trả về cho trang JSP ban đầu theo yêu cầu phía client.
  • MVC2 là một mô hình mô tả kiến trúc MVC trên nền web do Sun phát minh, khác với MVC1 trong MVC2 các Controller là các Servlet còn Model là các class của Java, view là các trang JSP. Ở MVC2 ta thấy các logic phức tạp được viết trong Controller (Hard working), các servlet nhận yêu cầu từ client qua sử lý được gửi cho Model và View để tương tác trả kết quả cho client.
  • Ta thấy MVC2 không kế thừa từ MVC1 nhưng làm việc hiệu quả và logic hơn.
  • MVC2 tốt cho các dự án lớn nhưng MVC1 thì không.
  • Với thành được phân chia theo chức năng, MVC2 có thể dễ dàng tái sử dụng.
  • Cũng chính vậy mà MVC2 phức tạp hợn MVC1.

2. Phân biệt 3 layer và 3 tier. 

  • 3 layer
  • 3 tier

Chúng ta thường tồn tại sự bối rối khi phân biệt 3 layer vs 3 tier, thật sự,  hơi khó tìm được ứng dụng thuần 1 trong 2 mô hình kiến trúc trên, phần nhiều là sự lai tạo và tùy biến kết hợp với design pattern cho phù hơp.

3 layer Architecture

Capture1

Hướng tiếp cận này phân tách ứng dụng thành từng phần mang tình logic:

  1. Presentation: Các form nhập liệu và kết quả trả lại.
  2. Business Logic: Trọng tâm các xử lí logic, nghiệp vụ.
  3. Data Access: Các thành phần lưu trữ và xử lí trên lưu trữ.

Mặc dù về mặt vật lí, các layer không tồn tại như đã ủy thác, nhưng thực tế kiến trúc này mang lại khả năng duy trì (maintenance) và khả năng dùng lại (reusability). Maintencance vì mỗi layer gồm 1 tập các APIs (Presentation layer, APIs như WinForms hay  , Atlas, Data Access layer, có thể là  ,  , Business layer). Reusability là khả năng có thể thêm Presentation layer cho các thiết bị di động, thay đổi thành phần lưu trữ dữ liệu bằng thành phần lưu dữ liệu khác hoặc Xml, nhưng sự thay đổi 1 layer không ảnh hưởng đến các layer khác. Các layer khác nhau khi được thực thi vẫn có thể nằm trong cùng một vùng bộ nhớ của một process, và hiển nhiên việc giao tiếp giữa 2 layer có thể không phải là giao tiếp giữa 2 process, đồng nghĩa với việc chúng không liên quan tới mô hình client/server.

3- Tier Architure

Theo wikipedia thì:

“3-tiers là một kiến trúc kiểu client/server mà trong đó giao diện người dùng (UI-user interface), các quy tắc xử lý(BR-business rule hay BL-business logic), và việc lưu trữ dữ liệu được phát triển như những module độc lập, và hầu hết là được duy trì trên các nền tảng độc lập, và mô hình 3 tầng (3-tiers) được coi là một kiến trúc phần mềm và là một mẫu thiết kế.” 

593px-Overview_of_a_three-tier_application_vectorVersion.svg

Theo 3 tier phân chia ứng dụng thành các phần vật lí (physical)

  1. Presentation tier (Client): Thống nhất trong 1 tập các phần cứng & cơ sở hạ tầng phần mềm khác nhau (giao diện cho user).
  2. Application tier (business logic, logic tier, or middle tier): Một hoặc nhiều máy chủ, cụm máy chủ, các yêu cầu từ Client được xử lí dựa trên HTTP, SMTP, SOAP hoặc các dạng khác dựa trên XML,…)
  3. Data tier: Máy chủ đóng vai trò chủ đạo tập trung các dịch vụ cấp thấp (truyền thông, bảo mật, …), vì thế cho phép các kênh khác nhau có thể truy cập vào các enterprise back-end.

Hướng tiếp cận này mang tính khả chuyển (Scalability), bảo mật tậptrung (Centrelized Security) khả năng quản lý lỗi (Fault Tolerance).

Đây là kiến trúc và tech stack của một dự án Logistic  mình từng làm.

Capture3.PNG

3. Code demo sử dụng JSP/ Servlet/ JavaBean. 

Tạo trang đăng nhập đơn giản theo mô hình MVC.

  • Một số kiến thức và công nghệ phục vụ phần demo của JSP/ Servlet/ JavaBean.
  • Demo Login theo mô hình MVC1.
  • Demo Login theo mô hình MVC2.
3.1. Một số kiến thức và công nghệ phục vụ phần demo của JSP/ Servlet/ JavaBean.

Một số kiến thức: 

Servlet (Controller):

  • Servlet là đoạn chương trình java thực thi trên Web Server hỗ trợ người lập trình java xây dựng trang web động.
  • Servlet nhận request từ client, sau đó thực hiện yêu cầu xử lí để response.
  • Cơ chế hoạt động: Khi có request từ client gửi đến Server hay Web Container,
    Container sẽ lựa chọn 1 instance Servlet tương ứng để đáp ứng request đó Servlet lựa chọn để thực hiện xử lí và kết nối DB nếu cần. Sau khi servlet thực hiện xong, sẽ gửi kết quả ra container để gửi response về cho người dùng.
  • Khi servlet chấp nhận lời gọi từ client, nó sẽ đón nhận 2 tham số là:
    • ServletRequest (đối tượng chứa đựng dữ liệu truyền từ client đến server).
    • ServletResponse (đối tượng chứa đựng dữ liệu được truyền từ server đến client).
    • Khi servlet áp dụng protocol HTTP để giao tiếp thì các thành phần mở rộng từ 2 lớp trên tương ứng được cung cấp đó là HttpServletRequest và HttpServletResponse.
  • Servlet định nghĩac: request, session, ServletContext. Đây là vùng không gian bộ nhớ được cung cấp cho mỗi ứng dụng web để chứa các thông tin để giao tiếp với các thành phần khác trong server.
    • request: tồn tại từ lúc gửi request cho đến khi response.
    • session: 1 khoảng thời gian từ lúc mở trình duyệt đến đóng trình duyệt, hết thời gian session, session bị hủy…
    • ServletContext: hiểu đơn giản là application tồn tại từ lúc bắt đầu ứng dụng đến khi ứng dụng bị undeploy ra khỏi server hay server bị crash.
  •  Servlet cung cấp thêm 1 interface RequestDispatcher hỗ trợ việc giao tiếp và xác định view tương ứng trong xử lí.

JavaBeans (Model)

  • Là 1 java class implements từ Serializable vì là object sử dụng qua protocol và giao tiếp với thành phần trong và ngoài server.
  • Buộc phải có 1 constructor không tham số để khởi tạo object=>thao tác không bị lỗi khi giá trị thuộc tính chưa cập nhật.
  • Cài đặt đầy đủ các phương thức và hành vi mà JavaBeans cần giao tiếp với thế giới bên ngoài.

Jsp (View):

  • Đây là ngôn ngữ scripting dùng ở server để hỗ trợ ứng dụng trong việc trình bày trang dynamic web .
  • JSP tích hợp HTML, XML, Java Code, kể cả Servlet.
  • Bản chất JSP là Servlet-> các thành phần của Servlet sẽ có tồn tại hết trên JSP.
  • Ngoài ra, JSP ko cần biên dịch mà nó được biên dịch khi có request lần đầu tiên yêu cầu đến server.
  • Kết xuất JSP thực chất là HTML, File JSP có phần mở rộng là .jsp
  • Khi có 1 yêu cầu từ client đến server, container xác định trang jsp được yêu cầu. Trang JSP được đưa qua JSP Engine để xử lí. JSP Engine thực hiện các bước:
    • Đọc cấu trúc file của JSP File từ trên xuống dưới, từ trái qua phải để chuyển đổi sang java code tương ứng.
    • Phát sinh Servlet từ nội dung parsing ở bước trên để cấu tạo thành servlet.
    • Thực hiện biên dịch code Servlet.
    • Sau khi biên dịch thành công thì quá trình hoạt động sẽ thực hiện đúng theo chu kì.
  • JSTL: JSP Standard Tag Library định nghĩa ra các tag hỗ trợ chức năng xử lý trên trang JSP một cách đơn giản và rõ ràng. Chúng gồm các tag như core, sql, fmt – format, xml, function.

Mình sử dụng những công nghệ sau:

  • Tools sử dụng ở đây là Netbeans 8.2.
  • JDK 8 update 66 hay JDK 7 update 51 – khuyến cáo sử dụng JDK 7 là ổn định nhất.
  • Server: Tomcat 8.0.27, 7.0.41 hoặc GlassFish 4.1.1.

Bạn tạo cấu trúc project: New Project -> Java Web -> Web Application -> Create Project name -> Choose Server -> Done

3.2. Demo login theo mô hình MVC1.

(Project này gồm View – Controller: index.jsp, nameprocess.jsp, another.jsp/ Model: bean.users.java)

Capture2

index.jsp

<%@page contentType="text/html" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <title>JSP Page</title>
    </head>
    <body>
<h1>anc</h1>
<form action="nameprocess.jsp">
            <input name="name"/>
            <input type="submit"/>
        </form>

    </body>
</html>

nameprocess.jsp

<%@page import=" bean.users "%>
<%@page contentType="text/html" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <title>Processing your name</title>
    </head>
    <body>
<h1>Hello Controller!</h1>
<jsp:useBean class="bean.users" id="user" scope="session" />
        <jsp:setProperty name="user" property="name" param="name" />
        <a href="another.jsp"> Another page</a>
    </body>
</html>

another.jsp

<%@page contentType="text/html" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <title>Another page</title>
    </head>
    <body>

        <jsp:useBean class="bean.users" id="user" scope="session"/>
<h1>Result View!</h1>
<jsp:getProperty name="user" property="name"/>
    </body>
</html>

bean.users.java

package bean;

/**
 *
 * @author viquy
 */
public class users {
    private String name;

    public users() {
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

}

3.2. Demo Login theo mô hình MVC2.

(Project này gồm View: index.html, login-error.jsp, login-success.jsp/ Model: bean.LoginBean/ Controller: controller.ControllerServlet)

Capture2

View:  index.html

<html>
    <head>
        <title>TODO supply a title</title>
<style>
            .input{height: 20px; width: 200px; margin-bottom: 5px}
        </style>

        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
    </head>
    <body>
<div style="border-radius: 5px; width: 200px; margin: 50 px auto; background: rgb(256,256,256); padding: 50px">
<form action="ControllerServlet" method="post">
                Name:
 <input class="input" type="text" name="name"></br>
                Password:
 <input class="input" type="password" name="password"></br>
                <input style="width: 100px; height: 24px; margin-top: 15px;" type="submit" value="login" >
            </form></div>
</body>
</html>

login-error.jsp

<%@page import=" bean.LoginBean "%>
<%@page contentType="text/html" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <title>JSP Page Login Error</title>
    </head>
    <body>
<h3>
            Login fail :v <a style="color: rgb(37, 232, 230); margin: center"/>
            <%@include file="index.html" %>
            <a href="login-success.jsp"></a></h3>
</body>
</html>

login-success.jsp

<%@page import=" bean.LoginBean "%>
<%@page contentType="text/html" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <title>JSP Page Login</title>
<style>
            .title{margin: 20 px auto; font-size: 20px; font-weight: bold; width: 320px}
            .titlep{margin-top: 50px}
        </style>

    </head>
    <body>
<form action="login-success.jsp" method="post"

                <jsp:useBean id="bean" class="bean.LoginBean" scope="request" />
<h3>
                Welcome <a style="color: rgb(37, 232, 230); margin: center"/><%=bean.getName()%>
                <%@include file="index.html" %></h3>
</form>

    </body>
</html>

Model: bean.LoginBean

package bean;

/**
 *
 * @author viquy
 */
public class LoginBean {
    private String name, passWord;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getPassWord() {
        return passWord;
    }

    public void setPassWord(String passWord) {
        this.passWord = passWord;
    }
    public boolean validae(){
        if(passWord.equals("admin")){
            return true;
        }else{
            return false;
        }
    }
}

Controller: controller.ControllerrServlet.java (Servlet)

package controller;

import bean.LoginBean;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 *
 * @author viquy
 */
public class ControllerServlet extends HttpServlet {

    /**
     * Processes requests for both HTTP <code>GET</code> and <code>POST</code>
     * methods.
     *
     * @param request servlet request
     * @param response servlet response
     * @throws ServletException if a servlet-specific error occurs
     * @throws IOException if an I/O error occurs
     */
    protected void processRequest(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        response.setContentType("text/html;charset=UTF-8");
        try (PrintWriter out = response.getWriter()) {
            /* TODO output your page here. You may use following sample code. */
            out.println("<!DOCTYPE html>");
            out.println("<html>");
            out.println("<head>");
            out.println("<title>Servlet ControllerServlet</title>");
            out.println("</head>");
            out.println("<body>");
            out.println("
<h1>Servlet ControllerServlet at " + request.getContextPath() + "</h1>
");
            out.println("</body>");
            out.println("</html>");
        }
    }

    // <editor-fold defaultstate="collapsed" desc="HttpServlet methods. Click on the + sign on the left to edit the code.">
    /**
     * Handles the HTTP <code>GET</code> method.
     *
     * @param request servlet request
     * @param response servlet response
     * @throws ServletException if a servlet-specific error occurs
     * @throws IOException if an I/O error occurs
     */
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        processRequest(request, response);
    }

    /**
     * Handles the HTTP <code>POST</code> method.
     *
     * @param request servlet request
     * @param response servlet response
     * @throws ServletException if a servlet-specific error occurs
     * @throws IOException if an I/O error occurs
     */
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        String name = request.getParameter("name");
        String passWord = request.getParameter("password");
        LoginBean bean = new LoginBean();
        bean.setName(name);
        bean.setPassWord(passWord);
        request.setAttribute("bean", bean);
        boolean status=bean.validae();
        if(status){
            RequestDispatcher rd=request.getRequestDispatcher("login-success.jsp");
            rd.forward(request, response);
        }else{
            RequestDispatcher rd=request.getRequestDispatcher("login-error.jsp");
            rd.forward(request, response);
        }
    }

    /**
     * Returns a short description of the servlet.
     *
     * @return a String containing servlet description
     */
    @Override
    public String getServletInfo() {
        return "Short description";
    }// </editor-fold>

}

Mong rằng bài viết này sẽ có ích, chúc các bạn một ngày tràn đầy năng lượng 😀

Advertisement

Privacy Settings

Share this:

Like this:

Like

Loading…