Thứ Hai, 8 tháng 9, 2014

Servlet Context

Một trường hợp mà servlet context có thể phát huy tác dụng: Giả sử ứng dụng web của bạn có 2 servlet class, và cả 2 đều phải lấy 1 giá trị từ web.xml, trong trường hợp này ServletContext sẽ rất hữu ích vì tất cả các servlet trong cùng 1 ứng dụng web đều có thể truy cập vào các giá trị ở mức context như thê.

Bạn có thể truy cập vào nó thông qua HttpRequest, như thế này:
ServletContext context = request.getServletContext();


Context Attributes

Giống như session, bạn cũng có thể lưu giá trị vào servlet context như sau:

context.setAttribute("NameOfValue",Value);

và lấy giá trị theo tên như sau:

Object attribute = context.getAttribute("NameOfValue");

ServletContext khác với Session ở chỗ, giá trị lưu ở ServletContext có thể được truy cập bởi tất cả các servlet, giữa các requests và sessions. Điều đó có nghĩa giá trị lưu trong ServletContext có thể được dùng cho tất cả các khách ghé thăm trang web. Còn giá trị lưu trong session thì chỉ có 1 khách duy nhất truy cập được.

How to Use:

Chúng ta sẽ tạo một ứng dụng web đếm số lần trang web được ghé thăm

Đầu tiên, chúng ta sẽ tạo 1 servlet có tên là Page1 như sau (Servlet Page2 tương tự):

public class Page1 extends HttpServlet {

    protected void processRequest(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        response.setContentType("text/html;charset=UTF-8");
        try (PrintWriter out = response.getWriter()) {
           
            out.println("<!DOCTYPE html>");
            out.println("<html>");
            out.println("<head>");
            out.println("<title>Servlet NewServlet</title>");            
            out.println("</head>");
            out.println("<body>");
            
            ServletContext context = request.getServletContext();
            Integer count =  (Integer) context.getAttribute("count");
            ìf(count!=null){
                 count = 1;
            }
            
            count++;
            context.setAttribute("count",count);

            out.println("<h1>Page Views " + count + "</h1>");
            out.println("</body>");
            out.println("</html>");
        }
    }
}

Bây giờ, mỗi lần chúng ta refesh Page1 thì count sẽ tăng lên 1. Và nếu chúng ta refresh Page 2 thì count sẽ tăng lên 1 từ giá trị count mới nhất từ Page1. Điều đó có nghĩa là 2 servlet Page1 và Page2 cùng có thể truy cập vào giá trị của count ở mức context của ứng dụng web.

Session In Java Web

Một ví dụ của việc dùng session trong việc phát triển ứng dụng web là đặc điểm shopping cart của các trang web mua hàng. Khi bạn chọn lựa và thêm các item vào giỏ hàng, session sẽ nhớ các lựa chọn của bạn; như vậy shopping cart của bạn sẽ có những sản phẩm mà bạn đã lựa chọn khi bạn check out. Nếu k có session, nếu bạn checkout, cái trang mới mà bạn sắp chuyển hướng đến sẽ không nhận biết được các hoạt động mà bạn đã làm từ những trang trước và giỏ hàng sẽ trống trơn, luôn luôn là như vậy. 

Như vậy, Website sử dụng session để chắc chắn rằng nó sẽ nhận ra bạn khi bạn chuyển trang trong cùng một website hoặc khi bạn refesh trang. 

Các phương thức để quản lý session:

URL Rewriting: các client có thể gửi thông tin đến server bằng cách thêm ID của session vào địa chỉ URL cùng với các requests. Việc này khá gây mệt mỏi vì tự chúng ta phải theo dõi các tham số này trong mỗi response từ server và phải đảm bảo rằng các ID của các session k trùng nhau

Hidden Form Variables: Chúng ta có thể tạo các trường ẩn trong HTML và khi người dùng bắt đầu chuyển hướng, chúng ta có thể gán 1 giá trị duy nhất cho người dùng đó, đồng thời theo dõi được các session. Độ bảo mật khi dùng phương pháp này là không cao bới vì chúng ta rất dễ dàng lấy được giá trị từ những trường ẩn này từ HTML

Ngoài ra, còn có những phương thức khác như Persistent Cookies, Persistent Mechanism hay Servlet APIs.., Trong đó, Servlet APIs được xây dựng dựa trên các phương thức trên

Cách sử dụng Session

Chúng ta sẽ tạo một ứng dụng web nhằm lưu username của người dùng vào session rồi sau đó hiển thị ở trang sau:

Đầu tiên, tạo 1 trang HTML như sau:


Sau khi người dùng nhập username và nhấn Login, Servlet Login sẽ kiểm tra xem username có trong database không

Tiếp theo, chúng ta tạo Servlet Login như sau:

public class Login extends HttpServlet {

    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 Login</title>");
            out.println("</head>");
            out.println("<body>");

            String username = request.getParameter("username");
            if (userList.contains(username)) {
                HttpSession session = request.getSession();
                session.setAttribute("username", username);
                RequestDispatcher rd = request.getRequestDispatcher("Logined");
                rd.forward(request, response);
            }
            out.println("<h1>UserName Mismatch " +"</h1>");

            out.println("</body>");
            out.println("</html>");
        }
    }
    protected List<String> userList = null;

    @Override
    public void init() throws ServletException {
        userList = new LinkedList<>();
        userList.add("Long");
        userList.add("Hoang");
        userList.add("Tuan");

    }
}

Ở trên, chúng ta có 1 mock data là userList được khởi tạo và thêm phần tử ở hàm init().
Ở hàm processRequest(), username được lưu vào 1 session có tên là "username" thông qua session.setAttribute("SessionName", SessionValue) rồi sau đó chuyển hướng trang sang Logined Servlet 

Tại Servlet Logined, giá trị của session có tên là "username" được lấy ra thông qua session.getAttribute("SessionName") và hiển thị trong hàm processRequest:

 protected void processRequest(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        response.setContentType("text/html;charset=UTF-8");
        try (PrintWriter out = response.getWriter()) {
         
            out.println("<!DOCTYPE html>");
            out.println("<html>");
            out.println("<head>");
            out.println("<title>Servlet Logined</title>");            
            out.println("</head>");
            out.println("<body>");

             HttpSession session = request.getSession();
            String username = (String) session.getAttribute("username");

            out.println("<h1>Hello, " + username + "</h1>");
            out.println("</body>");
            out.println("</html>");
        }
    }

Use Request Dispatcher

ĐỀ BÀI:

Implement an application as following:
Depends of the question, GateKeeper will forward request to corresponding Answers.

1. Tạo trang HTML:
Chúng ta tạo 1 trang index.HTML đơn giản như sau:

GateKeeper là 1 servlet, có nhiệm vụ nhận thông tin từ trang index.html và chuyển hướng tới các servlets khác tương ứng với câu hỏi từ input có name là question.

2. Tạo Servlet GateKeeper

Tạo 1 List số để so sánh với input của người dùng:

                private List<String> answerCodes = null;
               @Override
                public void init() throws ServletException {
                      answerCodes = new LinkedList<>();
                      answerCodes.add("1");
                      answerCodes.add("2");
                      answerCodes.add("3");
                }

Xử lý hàm processRequest của Servlet này như sau:

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 GateKeeper</title>");            
            out.println("</head>");
            out.println("<body>");

            String question = request.getParameter("question");
            List<String> collect = answerCodes.stream().filter(s -> question.contains(s)).collect(Collectors.toList());
            
            if(collect!= null){
                RequestDispatcher rd = request.getRequestDispatcher("Answer" +collect.get(0));
                rd.forward(request, response);
            }
            

            out.println("<h1>No corresponding answer " + "</h1>");
            out.println("</body>");
            out.println("</html>");
        }
    }

Hàm "filer" ở trên sẽ lọc các phần tử thỏa mãn điều kiện input của người dùng chứa mã câu hỏi nào (answerCode) thì sẽ trả về mã câu hỏi đó. Ví dụ, nếu input của người dùng có giá trị là "a1" thì biến collect sẽ chứa answerCode là 1. Còn nếu giá trị input của người dùng k thỏa mãn điều kiện trên thì sẽ hiện thông báo "No corresponding answer".

Trường hợp collect != null, GateKeeper sẽ chuyển hướng sang những servlet tương ứng.Ví dụ Servlet Answer1 như sau:

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 Answer1</title>");          
            out.println("</head>");
            out.println("<body>");
                     
            out.println("<h1>Question1" + "</h1>");
            out.println("<h1>Question1 answered"+"</h1>");
            out.println("</body>");
            out.println("</html>");
        }
    }

Thứ Sáu, 5 tháng 9, 2014

Servlet Initialization Parameters

Chúng ta có thể tùy chỉnh các tham số khởi tạo của servlet ngay trước khi chúng được khởi tạo và đưa vào phục vụ. Việc xác định các tham số khởi tạo này cho phép servlet có thể thực hiện được các nhiệm vụ mà chỉ cần làm một lần duy nhất bằng cách override phương thức init() của Servlet interface.

Những tham số khởi tạo được truyền vào servlet từ file web.xml. Chúng chỉ được sử dụng duy nhất bởi chính servlet đó. Sau đây là cách chúng ta config web.xml để khởi tạo tham số:

<servlet>
        <servlet-name>NewServlet</servlet-name> 
        <servlet-class>NewServlet</servlet-class>
        <init-param> 
             <param-name>myParam</param-name> 
             <param-value>paramValue</param-value> 
        </init-param>
</servlet>



Sau đây là cách chúng ta lấy các tham số khởi tạo ra từ trong servlet - cụ thể là trong phương thức init():

public class NewServlet extends HttpServlet {
    protected String myParam = null; 
   @Override
    public void init(ServletConfig servletConfig) throws ServletException{ 
       this.myParam = servletConfig.getInitParameter("myParam"); 
    }    
    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 NewServlet</title>");          
            out.println("</head>");
            out.println("<body>");

            out.println("<h1>Initial Value Is " + myParam  + "</h1>");
            out.println("</body>");
            out.println("</html>");
        }
    }
}
Phương thức init(ServletConfig servletConfig) được gọi khi servlet container tải servlet lần đầu tiên. Không ai có thể truy cập vào servlet cho đến khi nó hoàn toàn được tải lên servlet container. Sau khi init() ở trên được gọi thành công, thì các tham số khởi tạo đã được lấy ra từ file web.xml thông qua servletConfig.getInitParameter("myParam") và sau đó output ra màn hình dưới dạng HTML
( out.println("<h1>Initial Value Is " + myParam  + "</h1>");)




           

Thứ Năm, 4 tháng 9, 2014

Develop A Web App

Để tạo một ứng dụng web bằng java, chúng ta nên dùng Netbeans 8.0 bản có Java EE để có thể tạo được ứng dụng web

Sau khi cài Netbeans 8.0, chạy chương trình. Các bước để tạo 1 ứng dụng web:

I. Create Java Web

1. Tạo mới một Web Application
Nhấn vào File >> New Project >>chọn Java Web >> Web Application, như hình:


Nhấn Next để tiếp tục

2. Chọn Name và Location

Chọn Name và Location cho project web vừa tạo


Nhấn Next để tiếp tục

3. Tùy chọn Server và Settings

Chọn server là Apache Tomcat - kèm theo NetBeans 8.0. Nếu chưa có thì phải download về và cài đặt bản phù hợp với Netbeans ver bạn đang dùng


Nhấn Next để tiếp tục

4. Kết thúc

Tiếp theo là chọn Framework, các bạn có thể tạm thời bỏ qua bước này. Nhấn Next để hoàn thành việc tạo 1 web app.

II. Create Servlet to serve Client

1. Tạo trang HTML(có sẵn mặc định là trang index.html trong project vừa tạo ở trên)
2. Tạo Servlet

Click  Source Packages folder >> chuột phải vào default package >> New >> Servlet và được kết quả:


Đặt tên cho Servlet rồi nhần Next >> tick vào ô Add Information to deployment descriptor >> Finish

Như vậy là chúng ta đã có 1 Web App với Server hoàn chỉnh.

Test Server bằng cách thêm markup cho index.html như sau:


Sau đó, chạy chương trình và nhấn vào link "new Link", kết quả hiển thị như sau thì có nghĩa server đã hoạt động:


Servlet LifeCycle

Servlet có một vòng đời nhất định và được quản lý bởi servlet container, bao gồm các giai đoạn  
  1. Tải Servlet Class.
  2. Tạo Instance of Servlet.
  3. Gọi phương thức init().
  4. Gọi phương thức service().
  5. Gọi phương thức destroy().
Giai đoạn 1, 2 and 3 chỉ được thực hiện 1 lần duy nhất khi servlet lần đầu tiên được tải.

Giai đoạn 4 được thực hiện nhiều lần - 1 lần/1 HTTP request.
Giai đoạn 5 được thực hiện khi servlet container dỡ bỏ (unload)servlet.
Mỗi giai đoạn được mô tả như sau

Tải Servlet Class

Trước khi một servlet có thể được gọi thì servlet container phải tải servlet class. Theo mặc định thì servlet sẽ không được tải khi chưa nhận được request đầu tiên nào. Tuy nhiên chúng ta có thể bắt container load servlet theo tùy chỉnh của chúng ta.

Tạo Instance của Servlet

Khi servlet class được tải, servlet container tạo 1 instance của servlet.
Bình thường,chỉ 1 isntance duy nhất của servlet được tạo, và những request đồng thời cùng lúc tới servlet sẽ được xử lý ở cùng 1 instance của servlet.

Gọi phương thức Servlets init()

Khi servlet instance được tạo, phương thức init() sẽ được gọi, cho phép servlet được khởi tạo trước khi request đầu tiền được xử lý.
Chúng ta có thể xác định tham số cho phương thức init() của servlet trong web.xml file. Xem web.xml Servlet Configuration.

Gọi phương thức Servlets service()

Đối với mỗi request mà servlet nhận được, nó sẽ gọi phương thức service(). Đối với HttpServlet subclasses, phương thức doGet(), doPost() etc sẽ được gọi.
Đến khi nào servlet còn hoạt động trong servlet container thì phương thức service() còn có thể được gọi. Vì thế giai đoạn này có thể được thực hiện nhiều lần

Gọi phương thức Servlets destroy()

Khi servlet container gỡ bỏ 1 servlet, phương thức destroy() của servlet sẽ được gọi. Bước này chỉ được thực hiện 1 lần vì 1 servlet chỉ được gỡ bỏ 1 lần duy nhất.
Một servlet sẽ được gỡ bỏ bởi container nếu container dừng hoạt động hoặc khi container tải lại toàn bộ ứng dụng web khi ứng dụng đang chạy.

Basic of HTTP


Hypertext Transfer Protocol (HTTP) là một giao thức không lưu trạng thái (stateless) và không giữ kết nối (connectionless),  nó là nền tảng của web và nhận trách nhiệm việc giao tiếp và trao đổi thông tin trong thế giới web chủ yếu thông qua TCP/IP

HTTP hoạt động như một giao thức request-response trong mô hình client-server. Ví dụ như một trình duyệt web có thể là client và một ứng dụng chạy trên một máy tính host trang web đó có thể là server. Các client gửi một  HTTP request đến server. Các server, cung cấp các nguồn tài nguyên như các tập tin HTML và nội dung khác, hoặc thực hiện các chức năng khác thay mặt cho client, trả về một response cho các client.



Giao thức HTTP là phi trạng thái (stateless) là do server không cần phải theo dõi trạng thái của các request khác nhau từ client, không phải là nó không thể làm như vậy, nó có thể nếu muốn. Điều này giúp đơn giản hoá giàng buộc giữa client và server, và trong nhiều trường hợp giảm thiểu lượng dữ liệu cần được chuyển giao. Nếu các server được yêu cầu để duy trì trạng thái của các request từ client thì cơ cấu phát hành và đáp ứng lại các request sẽ phức tạp hơn. Đối với các ứng dụng web cần lưu lại trạng thái của người dùng thì có thể sử dụng HTTP persistent connection hoặc HTTP cookie

Ngoài ra, HTTP cũng không giữ kết nối (connectionless). Lý do chính là do khả năng mở rộng (scalibility). Duy trì một kết nối active cho mỗi client trở nên rất tốn kém tài nguyên. Hơn nữa, ý tưởng ban đầu của việc hình thành HTTP thể hiện dưới dạng "Hãy gửi cho tôi tài liệu X" rồi sau đó "Tài liệu X của bạn đây" rồi kết thúc- rất đơn giản. Vì thế việc duy trì kết nối trở nên không cần thiết.

Java Web Technologies


Hiện tại trên thị trường có rất nhiều công nghệ Java được sử dụng nhằm phát triển websites. Sau đây là những công nghệ đó: 

Java Servlet
Java Servlet cho phép bạn tạo ra các classes mà có thể xử lý được giao thức HTTP. Một class servlet có thể mở rộng được khả năng của server của một ứng dụng mà sử dụng mô hình request-response rất phổ biến trong ứng dụng web. Một Servlet chạy trên phía server mà không cần GUI hay HTML UI của riêng nó. Ví dụ như là bạn có thể sử dụng một servlet để nhập vào 1 chuỗi ở 1 textbox và in nó ra màn hình dưới dạng HTML... 
Dưới đây là một class servlet nhằm hiển thị các show truyền hình ra giao diện Web dưới định dạng HTML:
import java.io.*;
import java.text.SimpleDateFormat;
import javax.servlet.*;
import javax.servlet.http.*;

public class ScheduleServlet extends HttpServlet {
    public void doGet(HttpServletRequest request //request của người dùng,
            HttpServletResponse response //response từ server) throws IOException,
            ServletException {

        SimpleDateFormat dateFmt = new SimpleDateFormat("hh:mm a");

        Show[] shows = Schedule.getInstance().getTodaysShows( ); //lấy cac show truyền hình ra 

        response.setContentType("text/html");
        PrintWriter pw = response.getWriter( );
        pw.println("<html><head><title>Today's Shows</title></head><body>");
        pw.println("<h1>Today's Shows</h1>");
        pw.println("<table border=\"1\" cellpadding=\"3\"");
        pw.println(" cellspacing=\"0\">");

        pw.println("<tr><th>Channel</th><th>From</th>");
        pw.println("<th>To</th><th>Title</th></tr>");

        for (int i=0; i<shows.length; i++) {
            pw.println("<tr>");
            pw.print("<td>");
            pw.print(shows[i].getChannel( ));
            pw.println("</td>");
            pw.print("<td>");
            pw.print(dateFmt.format(shows[i].getStartTime( )));
            pw.println("</td>");
            pw.print("<td>");
            pw.print(dateFmt.format(shows[i].getEndTime( )));
            pw.println("</td>");
            pw.print("<td>");
            pw.print(shows[i].getTitle( ));
            pw.println("</td>");
            pw.println("</tr>");
        }
        pw.println("</table>");
        pw.println("</body>");
        pw.println("</html>"); 
Tất cả các dòng lệnh print() ở đây có vẻ ít vì tính chất đơn giản của trang web chỉ là hiển thị ra thông tin của các show truyền hình, nhưng 1 trang web thực tế sẽ phải có hàng nghìn dòng print() và kết quả là lập trình viên sẽ gặp khó khăn trong việc duy trì và phát triển trang web của mình. Graphic designer sẽ khó có thể tham gia vào quá trình tạo UI cho trang web vì phải phụ thuộc vào lập trình viên để tạo và chỉnh sửa code. Mỗi thay đổi code nhỏ cũng cần phải complie, test và deploy lại.

JavaServer Pages (JSP)
Công nghệ JSP cho phép bạn tạo 1 trang web động một cách nhanh chóng và đơn giản. Thay vì chèn code HTML vào Java servlets, JSP cho phép chúng ta bắt đầu từ chính trang HTML tĩnh. Chúng ta có thể thêm các thể HTML ngay trên trang. 
Sau đây là ví dụ cải tiến của trang web hiển thị các show truyền hình trên khi sử dụng JSP
Schedule.jsp
 <%@ page import="java.text.*" %>
<%! SimpleDateFormat dateFmt = new SimpleDateFormat("hh:mm a"); %>
<html>
  <head>
    <title>Today's Shows</title>
  </head>
<body>
<h1>Today's Shows</h1>
<% Show[] shows = Schedule.getInstance().getTodaysShows( ); %>
<table border="1" cellpadding="3" cellspacing="0">
  <tr><th>Channel</th><th>From</th><th>To</th><th>Title</th></tr>

  <% for (int i=0; i<shows.length; i++) { %>
  <tr>
    <td><%= shows[i].getChannel( ) %></td>
 <td><%= dateFmt.format(shows[i].getStartTime( )) %></td>
 <td><%= dateFmt.format(shows[i].getEndTime( )) %></td>
 <td><%= shows[i].getTitle( ) %></td>
  </tr>
  <% } %>
</table>
</body>
</html>
    Schedule.jsp là 1 trang HTML với các nội dung động được gói trong các thẻ đặc biệt của JSP (<% %>). Khi người dùng lần đầu request một trang JSP, toàn bộ trang sẽ được biên dịch sang source code của 1 servlet và sau đó được tải vào bộ nhớ để dùng cho những request tiếp theo. Trong quá trình biên dịch các thẻ JSP (ở đây là <% %>) sẽ được thay thế bằng những dữ liệu động (ở đây là thông tin các show truyền hình) và hiển thị dưới dạng HTML như thể toàn bộ trang là HTML tĩnh. 
    Performance của JSP tốt hơn khá nhiều so với Servlet bởi vì nội dung HTML tĩnh của JSP được tạo ra từ chính thẻ HTML thay thế một chuỗi các dòng lệnh print() của servlet. Performance của JSP sẽ chậm 1 chút khi người dùng lần đầu tiên visit trang bởi nó sẽ phải biên dịch code. Tuy nhiên, JSP cung cấp các tùy chọn cho việc biên dịch trước nhằm tránh việc này xảy ra.

    JavaServer Pages Standard Tag Library
    JavaServer Pages Standard Tag Library bao gói các chức năng phổ biến của công nghệ JSP. Thay vì trộn thẻ từ nhiều nhà cung cấp trong các ứng dụng của bạn, bạn sử dụng một thư viện thẻ tiêu chuẩn nhất định. 
    JavaServer Faces Technology
    JavaServer Faces là một UI framework nhằm phát triển ứng dụng web. Thành phần chính của nó bao gồm các GUI component framework, và đặc biệt là bộ RenderKit nhằm tạo ra các HTML markup. 
    JavaServer Faces tận dụng khả năng drag-and-drop các GUI components, cho phép bạn sử dụng công nghệ này mà không cần thiết phải viết hay hiểu code nền bên dưới.

    Client-Server Model

    Ngày nay, hầu hết các ứng dụng sử dụng mạng đều áp dụng mô hình Client-Server. Vậy mô hình Client-Server là gì? Khái niệm này bao gồm 2 quá trình hoặc là 2 đối tượng là Client và Server sẽ tương tác với nhau để trao đổi thông tin. Quá trình thứ nhất là Client gửi yêu cầu về cho Server và quá trình thứ 2 là Server xử lý yêu cầu và trả lời lại Client. Hình ảnh dưới đây thể hiện quá trình đó:



    Một ví dụ của mô hình này là quá trình kiểm tra số dư tài khoản ngân hàng của bạn. Một chương trình ở máy khách chuyển yêu cầu đến cho Server đạt tại ngân hàng để lấy ra số dư tài khoản ngân hàng của bạn. Số dư đó sau đó được chuyển tiếp trở lại cho máy khách và hiển thị chúng theo giao diện chương trinh bạn đang sử dụng.

    Chúng ta thường sử dụng mô hình này khi phát triển ứng dụng phân tán. Lý do đơn giản bắt nguồn từ chính nhu cầu của người dùng khi mà họ không sống cùng ở một địa điểm, tuy nhiên họ lại muốn thực hiện cùng một nhiệm vụ hay dùng chung một dữ liệu nào đó. Khi đó mô hình client-server trở nên rất phù hợp trong trường hợp này.

    Những mô hình quan hệ khác có mức độ phổ biến cao đó là mô hình peer-to-peer (P2P), trong đó mỗi điểm của mô hình đều có thể hoạt động như là 1 server và 1 client. Điều này có nghĩa là, không giống như mô hình client-server, khả năng phân phát dữ liệu có thể tăng lên khi mà càng nhiều người dùng muốn sử dụng chung 1 nguồn dữ liệu (giống với giao thức chia sẻ file của Bittorrent). Đây chính là một trong những điểm thuận lợi của mô hình P2P này khi mà nó tiêu tốn ít chi phí cài đặt và vận hành và bảo dưỡng của server hơn so với mô hình client-server


    Phương pháp học mới - Lớp Học Đảo Ngược (Flipped Classroom)

        Theo một cách đơn giản, lớp học bị đảo ngược đảo ngược lại phương pháp dạy của một lớp học truyền thống. Điều đó có nghĩa là những video bài giảng lý thuyết sẽ được làm và giao cho học sinh xem trước ở nhà và những gì từ trước đến giờ được coi là bài tập về nhà sẽ được làm ở trên lớp cùng với sự hướng dẫn của giáo viên cũng như sự tương tác với các bạn trong lớp.

        Vậy làm thế nào để có thể làm việc được với phương pháp học đảo ngược này, dưới tư cách là 1 học sinh?

        Chúng ta làm đúng theo định nghĩa của phương pháp học mới này: Đầu tiên là xem video bài giảng và đọc những bài đọc lý thuyết liên quan. Sau đó, lên lớp làm những bài tập thực hành từ nhỏ đến lớn dưới sự trợ giúp của giáo viên và những học sinh khác. 
        
        Ngoài ra, phương pháp này đạt được hiệu quả 1 phần cũng vì đi theo mô hình học tập Kolb, mà trong đó giai đoạn Reflection thường bị bỏ qua (More info on Kolb's learning process )


         Trong lớp học đảo ngược, học sinh sẽ trải qua giai đoạn đầu tiên của vòng tuần hoàn Kolb - tiếp cận với kiến thức mới khi mà họ xem trước nội dung bài học ở nhà. Sau đó, họ sẽ phải đi qua giai đoạn Reflection. Lớp học truyền thống thường thể hiện điều này dưới dạng bài tập về nhà, tuy nhiên với lớp học đảo ngược, giáo viên có thể dẫn dắt học sinh đi qua giai đoạn này bằng việc hỗ trợ khi học sinh gặp những khó khăn ở trên lớp. Giáo viên sau đó đưa học sinh qua giai đoạn hình thành khái niệm mới và thực hành rồi cuối cùng học sinh sẽ đạt được những kỹ năng đưa ra quyết định và giải quyết vấn đề nhằm sử dụng kiến thức mới học được trong những trường hợp khác. 
        
          Ngày nay, rất khó có thể phản biện lại việc học tốt nhất là bằng cách thực hành để lấy kinh nghiệm. Kolb đã thể hiện một điều rằng lớp học truyền thống chỉ cho chúng ta trải nghiệm được một phần của việc học và rằng việc học thực sự cần đi qua một chuỗi các giai đoạn. Một ví dụ điển hình của cách học truyền thống chính là việc nhồi nhét kiến thức một cách nhanh chóng cho một kỳ thi sắp đến, theo đó chúng ta có thể hoàn thành bài thi tốt nhưng kiến thức sẽ phai dần theo thời gian, việc mà rất nhiều học sinh đã không ít lần trải qua. Tuy nhiên với lớp học đảo ngược, kiến thức sẽ ở lại với chúng ta khi chúng ta trải qua bước Reflection của mô hình Kolb (quan sát, đối chiếu, nhận xét, so sánh khái niệm đang được học với những điều đã được học trước đó ). Vì thế, theo tôi Reflection chính là điểm quan trọng nhất của phương pháp học mới này.

        Ưu điểm của phương pháp học mới này là: học sinh sẽ có sự chủ động hơn trong học tập. Bằng việc cung cấp những video bài giảng ngắn để học tại nhà, học sinh có sự thoải mái học tập tại chính nhà của họ. Họ có thể dừng hoặc xem lại bài giảng,viết lại những thắc mắc rồi sau đó thảo luận với thầy cô và bạn bè ở trên lớp. Phương pháp học này cũng cho phép học sinh có nhiều thời gian hơn để hiểu một khái niệm mới và nhận sự trợ giúp ngay lập tức từ mọi người. Tuy nhiên, nó cũng có nhược điểm là việc học có thể bị gián đoạn khi chúng ta dành thời gian ngồi trước màn hình máy tính và bị những facebook notifications hay những cám dỗ khác thu hút.