Thứ Năm, 21 tháng 6, 2012

Kỹ thuật Web: Giao tiếp với người dùng. Phần 2

Kỹ thuật Web: Giao tiếp với người dùng. Phần 2


Mức độ khó: 2
Yêu cầu: Xem qua phần 1 chủa chuỗi bài viết.
Mong rằng sau khi đọc phần 1, các bạn đã hiểu qua khái niệm và cách thức gửi Request tới server. Ở phần này chúng tôi xin nói về việc đọc nội dung của Reuqest đuợc gửi và trả lời một cách đơn giản dưới một góc độ vừa đủ hiểu cho các lập trình viên.


Lắng nghe -> Nhận Request -> Xử lý -> Gửi Response -> Lắng nghe ->... Đây là quy trình làm việc của tất cả các web-server. Trong thực tế, các chuơng trình web-server đều bao gồm 1 vòng lặp vô tận với các kỹ thuật lập trình "Concurrency/Multithreading" mục đích thực hiện chuỗi công việc trên - nó lắng nghe và gửi trả từ vào các "stream" mà để giải thích chúng ta lại cần nói khá nhiều về mạng máy tính. Ở mức độ của bài viết này, ta không cần quan tâm tới các giai đaọn trên, hãy nhìn mọi việc với góc độ đơn giản, mỗi khi có 1 request là chuơng trình của bạn bắt đầu xử lí các request đó, và có những hàm rất đơn giản để bạn output dữ liệu cho người dùng. Ta sẽ thực hiện công đoạn tính toán cho ví dụ 01 ở phần 1.

Full Code Golang:
Chúng ta tạo 1 project mới cho ứng dụng tuơng đối hoàn thiện này với cấu trúc như sau:
WorkSpace/GO/apps/tinhtong/
WorkSpace/GO/apps/tinhtong/app.yaml
WorkSpace/GO/apps/tinhtong/sources/tinhtong.go

Nội dung file app.yaml:
===========================

application: tinhtong
version: 1
runtime: go
api_version: go1




handlers:
- url: /.*
  script: _go_app
===========================

Nội dung file tinhtong.go:
  1. package helloworld
  2. import (
  3.         "fmt"
  4.         "net/http"
  5.         "strconv"
  6. )
  7. func init() {
  8.         http.HandleFunc("/", root)
  9.         http.HandleFunc("/tinhtong", handle)
  10. }
  11. const plusForm = `
  12. <html>
  13.         <body>
  14.                 <form name="input" action="/tinhtong" method="post">
  15.                 A: <input type="text" name="a" value="1" /><br />
  16.                 B: <input type="text" name="b" value="2" /><br />
  17.                 C: <input type="text" name="c" value="3" /><br />
  18.                 D: <input type="text" name="d" value="4" /><br />
  19.                 E: <input type="text" name="e" value="5" /><br />
  20.                 <input type="submit" value="Submit" />
  21.                 </form>
  22.         </body>
  23. </html>
  24. `
  25. func root(w http.ResponseWriter, r *http.Request) {
  26.         fmt.Fprint(w, plusForm)
  27. }
  28. func handle(w http.ResponseWriter, r *http.Request) {
  29.         a, err := strconv.Atoi(r.FormValue("a"))
  30.         if err != nil {
  31.                 http.Error(w, err.Error(), http.StatusInternalServerError)
  32.                 return
  33.         }
  34.         b, err := strconv.Atoi(r.FormValue("b"))
  35.         if err != nil {
  36.                 http.Error(w, err.Error(), http.StatusInternalServerError)
  37.                 return
  38.         }
  39.         c, err := strconv.Atoi(r.FormValue("c"))
  40.         if err != nil {
  41.                 http.Error(w, err.Error(), http.StatusInternalServerError)
  42.                 return
  43.         }
  44.         d, err := strconv.Atoi(r.FormValue("d"))
  45.         if err != nil {
  46.                 http.Error(w, err.Error(), http.StatusInternalServerError)
  47.                 return
  48.         }
  49.         e, err := strconv.Atoi(r.FormValue("e"))
  50.         if err != nil {
  51.                 http.Error(w, err.Error(), http.StatusInternalServerError)
  52.                 return
  53.         }
  54.         fmt.Fprint(w, a + b + c + d + e)
  55. }

Thực thi 2 lệnh sau với Terminal:
============================

cd WorkSpace/GO
./dev_appserver.py apps/tinhtong
============================
"cd" là lệnh chuyễn thư mục, nó giúp ta đỡ phải gõ những đường dẫn dài trong một số trường hợp.
Khi chạy ứng dụng (http://localhost:8080/) bạn sẽ nhận thấy form ví dụ ở phần trước, khi bấm submit, bạn sẽ đuợc dẫn tới trang hiễn thị kết quả phép tính (http://localhost:8080/tinhtong) chỉ hiễn thị duy nhất một con số kết quả.
Hàm init() ta quy định hàm xử lý URI plat "/tinhtong" là hàm handler, còn với tất cả các trường hợp còn lại sẽ được xử lý bởi hàm root.
Hàm root chỉ có nhiệm vụ xuất ra màn hình mã HTML tạo form.
Hàm handle, thực hiện quá trình chuyễn kiểu (dữ liệu nhận được từ formdata, ngoại trừ các file, còn lại đều nằm ở dang text) từ text string sang int với thư viện strconv. Một điểm đặc biệt của Golang là hàm có thể return nhiều giá trị, cho nên thay vào việc try-catch-exception, nhiều hàm trong Go đuợc viết trả về kèm theo 1 biến lưu trữ Error, để kiểm tra mọi việc có ổn thỏa hay không ta dựa vào biến err.
Hãy thử truy cập trực tiếp trang http://localhost:8080/tinhtong , bạn sẽ nhận đuợc 1 dòng thông báo strconv.ParseInt: parsing "": invalid syntax. Tại sao? hãy thử trả lời câu hỏi này, nếu đúng bạn đã nắm đuợc vấn đề!







Trả lời câu hỏi:
Khi bạn tru cập trực tiếp vào URL http://localhost:8080/tinhtong, không hề có 1 giá trị form value nào đuợc gửi(bạn đang truy cập duới method GET), cho nên giá trị trả về của các hàm r.FormValue("a"),.. là chuỗi rỗng, không thể chuyễn kiểu sang Int một cách đúng đắn.

Đọc thêm
Full Code PHP:
<?php
echo $_REQUEST["a"] + $_REQUEST["b"] + $_REQUEST["c"] + $_REQUEST["d"] + $_REQUEST["e"];
?>
PHP là một ngôn ngữ thông dịch, được thiết kế để làm việc dễ dàng cho nền web. PHP lưu các giá query string parameter cũng như form data vào đối tuợng $_REQUEST (đây là mảng kết hợp của PHP, giồng như map/dictionary), ngoài ra còn có đối tụơng $_GET, $_POST dùng khi bạn cần phục vụ cho 1 trường hợp cụ thể. echo là lệnh để output thông tin trả về cho nguời dùng. Việc cài đặt web-server chạy PHP có độ khó bằng 0 nên xin không nói tới. Đaọn code chỉ phục vụ việc tính toán (tuơng đuơng với hàm handle với ví dụ Golang). PHP rất dễ tính, chuỗi có dạng số có thể dùng trực tiếp trong tính toán, điều đó làm đoạn code PHP ngắn hơn hẵn (nhưng hiệu suất có thể thua xa Golang).

Không có nhận xét nào:

Đăng nhận xét