Spring MVC

Mục lục
1 Hibernate ................................................................................................................................ 2
1.1 1.2 ORM (Objet – relation Mapping).............................................................................................. 2 Kiến trúc Hibernate .................................................................................................................... 3 Interface ............................................................................................................................... 3 Một số interface chính ........................................................................................................ 4 Các interface callback......................................................................................................... 6 Type ...................................................................................................................................... 6 Các interface mở rộng ........................................................................................................ 7

1.2.1 1.2.2 1.2.3 1.2.4 1.2.5 1.3

Truy vấn trong Hibernate - HQL (Hibernate Query Language) ........................................... 7 Định nghĩa............................................................................................................................ 7 Các cách thực hiện việc truy vấn trong Hibernate .......................................................... 7 Cách thực thi câu truy vấn ................................................................................................. 8 Các thành phần trong câu truy vấn .................................................................................. 8

1.3.1 1.3.2 1.3.3 1.3.4

2

Spring MVC ......................................................................................................................... 13
2.1 2.2 Mô hình MVC trong ứng dụng web ........................................................................................ 13 Giới thiệu về Spring framework .............................................................................................. 14 IoC(Inversion of Control) ................................................................................................. 15 DI(Dependency Injection) ................................................................................................ 15

2.2.1 2.2.2 2.3 2.4

Giới thiệu về Spring MVC........................................................................................................ 16 Một số thành phần quan trọng trong Spring MVC ............................................................... 17 DispatcherServlet .............................................................................................................. 17 Controllers ......................................................................................................................... 21 Handler mappings ................................................................................................................. 21 Một số thành phần khác ............................................................................................................. 23 Hoạt động của Spring MVC ..................................................................................................... 23

2.4.1 2.4.2 2.4.3 2.4.4 2.5

3

JSTL (JSP Standard Tag Library) .................................................................................... 24
3.1 3.2 S à g ................................................................................................................................. 24 ...................................................................................................... 24 Các th viện th của S

3.2.1 3.2.2 3.3 3.3.1 3.3.2 3.3.3 3.3.4 3.4 h

Core ction g

các chức n ng sau .............................................................................. 25

Formatting Action: ........................................................................................................... 25 guy n t c thiết kế .................................................................................................................. 26 ui ớc đ t t n .................................................................................................................. 26 Scoped Variables vs. Scripting Variables ....................................................................... 26 Các thuộc t nh động .......................................................................................................... 26 i .............................................................................................................................. 26 eneral-Purpose and Conditional ................................................................................... 26

3.5

h Conditiona ................................................................................................................ 28

1 Hibernate Trong nhiều năm, persistence (việc lưu trữ một đối tượng lên ổ đĩa hay một thiết bị lưu trữ bền vững khác) là một vấn đề gây nhiều tranh cãi trong cộng đồng Java: Liệu “persistence” là vấn đề đã được giải quyết bởi công nghệ quan hệ và các mở rộng (ví dụ như các stored procedure) hay “persistence” là một vấn đề lớn cần phải được giải quyết bởi các mô hình thành phần Java đặc biệt như là các EJB entity bean; Ta nên code tay ngay cả các thao tác cơ bản nhất như create, read, update, delete trong SQL hay JDBC, hay các công việc này nên được tự động hóa; Làm thế nào để hệ thống đạt được tính khả chuyển đổi nếu mỗi hệ thống quản trị cơ sở dữ liệu (DBMS) lại có một hình thái ngôn ngữ của riêng nó (có các token, syntax, semantic riêng); Có nên từ bỏ SQL hoàn toàn và chuyển sang một công nghệ cơ sở dữ liệu mới, ví dụ như các hệ thống cơ sở dữ liệu đối tượng. Cuộc tranh luận vẫn còn tiếp tục nhưng hiện nay đã có một giải pháp nhận được sự chấp thuận ngày càng tăng. Giải pháp này có tên gọi là ánh xạ đối tượng/quan hệ (ORM – object/relational mapping). Hibernate là một sự hiện thực ORM mã nguồn mở. Hibernate là một dự án với mục tiêu trở thành một giải pháp hoàn chỉnh cho vấn đềquản lý dữ liệu persistent trong Java. Nó làm trung gian cho các tương tác của ứng dụng với một cơ sở quan hệ, giải phóng nhà phát triển để họ có thể tập trung vào các vấn đề nghiệp vụ. Hibernate kkông phải là một giải pháp bắt buộc (non-intrusive solution). Nghĩa là ta không cần phải theo các luật cụ thể cho Hibernate và các design pattern khi viết các logic nghiệp vụ và các class persistent. Do đó Hibernate tích hợp tốt với hầu hết các ứng dụng mới và đang tồn tại mà không yêu cầu những thay đổi đối với phần còn lại của chương trình. 1.1 ORM (Objet – relation Mapping) Một ánh xạ đối tượng/quan hệ (object/relational mapping) là một sự thường trú tự động (persistence) của các đối tượng thuộc một ứng dụng Java trong các table thuộc một

cơ sở dữ liệu quan hệ bằng cách sử dụng các metadata mô tả sự ánh xạ giữa các đối tượng và cơ sở dữ liệu. Về bản chất, ORM, làm việc thông qua sự chuyển đổi dữ liệu từ một dạng thể hiện này sang một dạng khác. Một giải pháp ORM cấu tạo bởi bốn phần sau:  Một API để thực hiện các giao thức CRUD cơ bản trên các đối tượng của các class persistent.  Một ngôn ngữ hoặc API để thực hiện các câu truy vấn trên các class và các thuộc tính của class.  Một tiện ích để xác định các ánh xạ metadata.  Một kỹ thuật cho việc hiện thực ORM để tương tác với các đối tượng giao dịch để thực hiện dirty checking, lazy association fetching và các chức năng tối ưu khác. 1.2 Kiến trúc Hibernate 1.2.1 Interface Các interface lập trình (programming interface) là điều đầu tiên cần biết về Hibernate để sử dụng nó trong tầng persistencecủa ứng dụng của bạn. Một mục tiêu chính của thiết kế API là giữ cho các interface giữa các thành phần phần mềm càng gần nhau càng tốt. Tuy nhiên trong thực tế, các ORM API không hề ít. Tuy vậy, ta cũng không cần phải hiểu tất cả interface Hibernate một lúc. Hình 1.1 mô tả các vai trò của của các interface Hibernate quan trọng nhất trong tầng nghiệp vụ (business layer) và tầng persistence (persistence layer). Tầng nghiệp vụ nằm trên tầng persistence, bởi vì tầng nghiệp vụ hoạt động như một client của tầng persistence trong một ứng dụng phân lớp truyền thống. Lưu ý rằng, một số ứng dụng đơn giản có thể không tách biệt logic nghiệp vụ khỏi logic persistence. Điều đó chỉ làm đơn giản lược đồ hơn.

Các interface này được hiện thực bằng code cơ sở ứng dụng. bao gồm JDBC.1. bạn có thể lưu trữ và rút trích các đối tượng persistent và điều khiển các transaction. .2 Một số interface chính Sử dụng các interface này.  Các interface Callback – là các interface cho phép ứng dụng phản hồi lại các sự kiện (event) xảy ra bên trong Hibernate.  Các interface được code cơ sở ứng dụng gọi để cấu hình Hibernate.Session interface: . Transaction và Query. JTA. CompositeUserType.Hình 1. JNDI. Tổng quan về Hibernate API trong kiến trúc phân tầng Các interface Hibernate được thể hiện trên hình trên có thể được phân thành các loại chính sau:  Các interface được các ứng dụng gọi để thực hiện các thao tác cơ bản CRUD và các lệnh truy vấn. Chúng bao gồm Session. 1. Hibernate sử dụng các API Java có sẵn. và IdentifierGenerator. Lifecycle và Validatable. gồm các interface như Interceptor.2. trong đó quan trọng nhất là interface Configuration.  Các interface giúp mở rộng các chức năng ánh xạ của Hibernate. JDBC cung cấp một trừu tượng hóa ban đầu các chức năng thông dụng của cơ sở dữ liệu quan hệ. cho phép hầu hết các cơ sở dữ liệu với một JDBC driver được Hibernate hỗ trợ. gồm các interface như UserType. JNDI và JTA cho phép Hibernate tích hợp với J2EE server ứng dụng.

Ứng dụng sử dụng một thực thể Configuration để xác định vị trí của các tài liệu ánh xạ (mapping document) và các thuộc tính xác định Hibernate và sau đó tạo ra SessionFactory. Đặc điểm này khá quan trọng vì trong một ứng dụng cần tạo và xóa các session mọi lúc. dễ dàng tạo và hủy. Hibernate có thể dò tìm ra những thay đổi các đối tượng trong đơn vị công việc này. - - Transaction interface o Interface Transaction là một API tùy chọn. o SessionFactory lưu lại các câu lệnh SQL đã tạo và các siêu dữ liệu (metadata) ánh xạ khác mà Hibernate sử dụng ở thời điểm chạy. Nó cũng là interface cho các hàm liên quan đến persistent. Nó cũng lưu các dữ liệu đã từng được đọc (được cache lại) trong một đơn vị công việc và có thể được sử dụng trong một đơn vị công việc trong tương lai (chỉ nếu các ánh xạ class và collection xác định rằng cache cấp hai này là cần thiết). SessionFactory interface o Ứng dụng tạo được một thực thể Session từ một SessionFactory. Tuy nhiên. o Định nghĩa của Hibernate về một session là một cái giữa connection và transaction. thay vào đó nó sẽ quản lý các transaction bằng code cơ sở của riêng nó. Nghĩa là các ứng dụng Hibernate có thể không sử dụng interface này. Các Hibernate session không có tính an toàn về thread (not threadsafe) nên được thiết kế để chỉ được một thread sử dụng một thời điểm. Một Transaction interface tách biệt (trừu tượng hóa) code ứng dụng khỏi sự hiện thực transaction bên dưới (có thể là transaction JDBC. UserTransaction JTA hoặc transaction CORBA) cho phép ứng dụng điều khiển các biên transaction (transaction boundary – cho phép xác định khi nào một transaction bắt đầu và kết thúc) thông qua một API nhất quán. Configuration interface Đối tượng Configuration được sử dụng để định cấu hình và boostrap Hibernate. Có thể hình dung về session như một bộ đệm hoặc một tập hợp các đối tượng đã được nạp vào có liên quan đến một đơn vị công việc. ví dụ như là việc lưu và rút trích đối tượng. . Nó được dùng chung cho nhiều thread ứng dụng. Điển hình là có một SessionFactory cho toàn ứng dụng. được tạo trong phần khởi tạo ứng dụng. có thể là trên mỗi request.o Một thực thể Session ít tốn tài nguyên (có tính lightweight). SessionFactory không có tính lighweight. nếu ứng dụng cần truy xuất nhiều database bằng cách sử dụng Hibernater thì cần một SessionFactory cho mỗi database.

4 Type Một thành phần cơ bản và rất mạnh của kiến trúc này định nghĩa của Hibernate về Type. giới hạn của số kết quả trả về bởi truy vấn và nhiệm vụ cuối cùng là thực thi truy vấn. Các ứng dụng Hibernate không cần hiện thực những callback này nhưng chúng sẽ có ích cho việc hiện thực các loại chức năng tổng quát. Các truy vấn được viết bằng HQL (Hibernate Query Language) hoặc bằng ngôn ngữ SQL nguyên thuỷ. .Lifecycle và Validatable: cho phép một đối tượng persistent phản hồi các sự kiện liên quan đến vòng đời (lifecycle) persistent của riêng nó. o Một thực thể Query có tính lightweight và không thể sử dụng ngoài Session đã tạo ra nó.io. Kiểu này có thể kéo dài qua nhiều cột.2.Calendar. java.o Điều này giúp cho các ứng dụng Hibernate có tính khả chuyển trên các môi trường thực thi và các container khác nhau. Điều này làm cho Hibernate trở nên đặc biệt linh hoạt và dễ mở rộng. 1. bao gồm các quan hệ (association).Serializable. 1. Có rất nhiều kiểu Hibernate đã được xây dựng sẵn. o Interface Criteria cũng tương tự như vậy. Một thực thể Query được dùng để bind các thông số truy vấn.Currency. Tất cả các thuộc tính persistent của class persistent. bao gồm tất cả các kiểu gốc củaJava (Java primitive) và nhiều class JDK. bao gồm các kiểu cho java. nó cho phép tạo và thực thi các truy vấn chuẩn hướng đối tượng.Interceptor cho phép ứng dụng xử lý các callback mà không buộc các class persistent hiện thực các API đặc trưng của Hibernate (Hibernate-specific API).3 Các interface callback Interface Callback cho phép các ứng dụng nhận một thông báo khi có một sự kiện xảy ra đối với một đối tượng – ví dụ như khi đối tượng được nạp vào. Query và Criteria interface o Interface Query cho phép thực hiện các truy vấn đến các cơ sở dữ liệu và điều khiển việc các truy vấn này được thực thi như thế nào. Cáchiện thực interface Interceptor được truyền đến các thực thể persistent như các thông số. được lưu hoặc bị xoá.2.util. . có môt kiểu Hibernate tương ứng. như là tạo ra các bản ghi kiểm toán (audit record). byte[] và java. Một đối tượng Type của Hibernate ánh xạ một kiểu của Java đến một kiểu cột của cơ sở dữ liệu (database column type). Gồm các interface như: .util.

3 Truy vấn trong Hibernate .1 Định nghĩa Hibernate cũng có một ngôn ngữ truy vấn cho riêng nó. FROM và WHERE. Khi các chiến lược này không đủ hiệu quả.  Các chiến lược ORM: phân cấp interface ClassPersister. MonetaryAmount một cách thuận tiện.  Quản lý kết nối JDBC: interface ConnectionProvider. gồm truy vấn theo chuẩn (query by criteria.HQL (Hibernate Query Language) 1. Về mặt cấu trúc HQL cũng tương tự như SQL với các mệnh đề SELECT. tính đa hình (polymorphism) và quan hệ association). Hibernate cho phép thêm vào các hiện thực của riêng người dùng bằng cách hiện thực một interface. HQL cũng hỗ trợ subselect nếu cơ sở dữ liệu bên dưới cũng hỗ trợ."Lapto p%")). Điều này cho phép ta chọn giữa nhiều chiến lược được xây dựng sẵn. gọi tắt là HQL.  Quản lý transaction: interface TransactionFactory.createQuery(“from Category c where c.2 Các cách thực hiện việc truy vấn trong Hibernate Thực ra trong Hibernate ta có thể dùng đến 3 cách để biểu diễn câu truy vấn. . Name. Ví dụ: session. QBE). Các điểm mở rộng gồm có:  Tạo khoá chính: interface IdentifierGenerator. Các interface UserType và CompositeType cho phép thêm vào kiểu riêng của người sử dụng.name like „Laptop%‟”).like("name".  Các chiến lược lưu trữ đệm – cache: interface Cache và CacheProvider.  Các chiến lược truy cập thuộc tính: interface PropertyAccessor. Hibernate còn hỗ trợ cho kiểu tuỳ chỉnh do người dùng tự định nghĩa (user-defined custom type).add(Expression.Cách thứ nhất là sử dụng HQL: Ví dụ: session.createCriteria((Category. 1.class).Hơn thế nữa.Các kiểu tuỳ chỉnh được xem như là một đặc tính chính của Hibernate và được khuyến khích dùng.  Tạo proxy: interface ProxyFactor.Cách thứ ba là sử dụng câu SQL trực tiếp với sự ánh xạ tự động tập kết quả thành các đối tượng.2. Đặc tính này giúp điều khiển các class ứng dụng được sử dụng rộng rãi như là Address.3. 1.3. tên là Hibernate Query Language. .Cách thứ hai là sử dụng hàm API Criteria cho truy vấn. .  Hỗ trợ hình thái ngôn ngữ SQL: class trừu tượng Dialect. QBC) và truy vấn theo ví dụ (query by example. Nhưng thật sự HQL là ngôn ngữ truy vấn hướng đối tượng với các khái niệm về thừa kế (inheritence). . Transaction và TransactionManagerLookup.5 Các interface mở rộng Nhiều chức năng mà Hibernate cung cấp có khả năng định cấu hình. 1.

name thành name được. và người sử dụng có thể chuyển sang trang kết quả kế tiếp hoặc quay lại trang kết quả trước đó. Như vậy là khi truy vấn ta không dùng tên cột trong bảng mà dùng tên thuộc tính. Do HQL sử dụng theo các khái niệm hướng đối tượng. Ví dụ: Query hqlQuery = session. Trang này chỉ hiển thị giới hạn một tập con của kết quả (ví dụ.setFirstResult(0). Hàm setMaxResult(10) giới hạn tập kết quả truy vấn đến 10 đối tượng đầu tiên được chọn ra (select) trong cơ sở dữ liệu.class). Interface Query hỗ trợ việc phân trang của kết quả truy vấn: Query query = session.createSQLQuery("select {c.*} from CATEGORY {c} where NAME like 'Laptop%'". Tên thuộc tính phải luôn được đi kèm với tên đối . Người sử dụng có thể nhìn thấy kết quả tìm kiếm (ví dụ. query.3 Cách thực thi câu truy vấn Interface cho việc truy vấn (query interface) Để tạo một thực thể Query mới ta có thể gọi hàm createQuery().createQuery("from User"). chương 7 “Retrieving objects efficiently”.setMaxResult(10).4 Các thành phần trong câu truy vấn . 10 nhân viên) vào một thời điểm. query. các bạn có thể tham khảo thêm tài liệu Hibernate in Action.3.Category.3.Ví dụ: session. câu truy vấn sẽ như sau: FROM Event e WHERE e. Nó cũng cho phép tạo ra các bí danh cho tên đối tượng. tìm các Nhânviên trong một công ty) trong một trang.Mệnh đề FROM Mệnh đề FROM cho phép xác định các đối tượng sẽ được truy vấn.Phân trang kết quả Phân trang là một kỹ thuật thường được sử dụng. Tên bí danh này có thể được sử dụng giống như trong câu truy vấn SQL ngoại trừ việc ở đây ta sử dụng nó để định danh các đối tượng thay vì định danh các bảng như trong SQL. 1.name = “Festival” Câu truy vấn này có một cái tên bí danh cho thực thể Event là e.name asc”). Trong tài liệu này chúng ta chỉ đề cập đến cách truy vấn đầu tiên. Một điểm cần lưu ý trong câu truy vấn HQL trên là nó đang truy vấn trên một thuộc tính của đối tượng Event: thuộc tính name. .createQuery(“from User u order by u. vì vậy không thể viết tắt e."c". Nếu cần tham khảo thêm về hai cách còn lại. Giả sử ta muốn truy vấn tất cả các thực thể Event có tên là “Festival”. 1.

Đối tượng cơ sở trong một truy vấn là đối tượng hiện diện trong mệnh đề FROM. Tuy nhiên phép JOIN trong HQL chỉ kết hợp các thuộc tính của đối tượng và các quan hệ. Nếu cần truy vấn các thực thể của đối tượng Event mà một người tham dự (Attendee) xác định sắp tham gia. Nếu đối tượng ở đầu phải của kết hợp không có đối tượng nào trùng khớp (match) ở đầu trái của kết hợp thì nó vẫn được trả về. Attendee a WHERE … Và danh sách kết quả sẽ chứa một phép tích Cartesian các đối tượng được truy vấn (phép tích Cartesian là kết quả của việc kết hợp mỗi dòng của môt bảng với mỗi dòng của một bảng khác) mà rất có thể nó không phải là sản phẩm ta mong muốn. o Các loại kết hợp HQL có nhiều kiểu kết hợp khác nhau. cũng như các tập hợp với đối tượng cơ sở của truy vấn. left (outer) join Trả về tất cả đối tượng ở đầu trái của kết hợp. ta có thể đặt một bí danh cho quan hệ được kết hợp và truy vấn trên các thuộc tính trong đối tượng được kết hợp.Kết hợp (Join) Trong SQL cũng có phép JOIN trả về dữ liệu từ nhiều bảng với một câu truy vấn duy nhất. Nếu cần truy vấn nhiều đối tượng có liên quan đến nhau (các đối tượng có quan hệ với nhau). Để truy vấn trên nhiều đối tượng có liên quan đến nhau. bất kể có hay không đối tượng trùng khớp ở đầu đối diện của kết hợp. ta phải kết hợp thuộc tính attendee với đối tượng Event trong câu truy vấn: FROM Event e join e. right (outer) join Trả về tất cả đối tượng ở đầu phải của kết hợp. Trong ví dụ trên.id = 321 Trong HQL. Khi truy vấn chỉ liên quan đến một đối tượng. ta không quan tâm đến table và column dữ liệu quan hệ bên dưới mà tập trung vào các thuộc tính của các đối tượng. . .attendee a WHERE a. đối tượng cơ sở là Event. thì chỉ cần một đối tượng List chứa các thực thể của đối tượng truy vấn. Rõ ràng là khi sử dụng HQL. full join Trả về tất cả đối tượng ở cả hai đầu kết hợp. các kiểu kết hợp này đều có trong SQL. Bảng sau tóm tắt các kiểu kết hợp Loại kết hợp Luật inner join Các đối tượng không phù hợp với nhau ở một trong hai đầu kết hợp sẽ bị loại bỏ. chỉ có một kiểu kết hợp là ngoại lệ.tượng. ta cần kết hợp (join) chúng trong mệnh đề FROM. inner join fetch Được sử dụng để truy xuất một đối tượng kết hợp hoặc một tập hợp các đối tượng bất kể có hay không outer-join hoặc lazy property trên quan hệ. Trong ví dụ trên. trong khi phép JOIN trong SQL kết hợp các bảng. Loại kết hợp này không có trong SQL. ta có thể kết hợp tất cả các quan hệ (nhiều-một và một-một). Quy tắc đặt tên cho bí danh của HQL là sử dụng chữ viết thường. mệnh đề FROM sẽ chứa nhiều đối tượng: Ví dụ: FROM Event e. Nếu đối tượng ở đầu trái của kết hợp không có đối tượng nào trùng khớp (match) ở đầu phải của kết hợp thì nó vẫn được trả về.

Ví dụ: FROM Event e INNER JOIN FETCH e.createQuery("query").name = :name AND e. một lần cho tên của Location và một lần cho trạng thái (state) của Location. Ví dụ: Session session = factory. ta chỉ muốn lấy tên của Event. Thay vào đó. Các đối tượng trong phép kết cũng có thể được trả về trong mệnh đề SELECT của câu lệnh HQL.address. right. Việc truy xuất toàn bộ đối tượng chỉ để lấy thuộc tính tên thì rất không hiệu quả. String query = " select e.location.openSession(). Giá trị trả về có thể là toàn bộ đối tượng. câu truy vấn chỉ cần truy xuất đến dữ liệu mong muốn: SELECT e. Kết hợp một lazy collection với inner join fetch sẽ làm cho collection này được trả về khi populated. e. Nếu muốn truy xuất hai thuộc tính. Sau đây là một ví dụ về cách thức truy vấn và xử lý truy vấn trên nhiều thuộc tính. o Phép chiếu: Phép chiếu là việc chọn các cột xác định của dữ liệu trả về từ một truy vấn.Mệnh đề SELECT Mệnh đề SELECT cho phép xác định một danh sách các giá trị trả về từ câu truy vấn. Giả sử thay vì trả về toàn bộ đối tượng Event trong câu truy vấn.name.location l WHERE l. Một đặc điểm của HQL là khả năng trả về các đối tượng mới từ các giá trị được chọn. Giải thích: Nếu không dùng phép kết hợp join này ta có thể có câu truy vấn sau: FROM Event e WHERE e.startDate FROM Event e Mỗi phần tử trong danh sách trả về là một array kiểu Object (Object[]) chứa các giá trị xác định. Xét sự kết hợp một đối tượng có quan hệ một-nhiều với một đối tượng cơ sở: FROM Event e JOIN e.speakers Câu truy vấn này sẽ trả về tất cả các thực thể Event với các tập hợp của Speakers (nghĩa là một thực thể Event sẽ có một tập các Speaker tương ứng với Event đó). . Giá trị dẫn xuất bao gồm kết quả từ các hàm chức năng. Kết hợp Location với Event trong mệnh đề FROM sẽ chỉ phải thực hiện phép kết một lần và truy vấn cũng thực hiện hiệu quả hơn.location. Chiều dài của array Object[] bằng với số cột được yêu cầu truy xuất. ví dụ như ngày bắt đầu và tên của Event: SELECT e. .name. Query query = session.state = :state Vì ta phải duyệt qua các đối tượng hai lần.name = :name Kết hợp thực thể Location với đối tượng Event cho phép truy vấn trên các thuộc tính của Location. do đó trình biên dịch truy vấn sẽ kết hợp thực thể Location với Event hai lần.Loại kết hợp mặc định được sử dụng là inner join.name FROM Event e Câu truy vấn này trả về một danh sách các thực thể kiểu chuỗi chứa các tên của Event. ngoại trừ inner join fetch. và đạt được kết quả truy vấn hiệu quả hơn. full). như là hàm min(). max() và hàm count(). Muốn sử dụng loại khác ta phải xác định chính xác loại kết hợp trong mệnh đề kết hợp (left. các thuộc tính xác định của đối tượng và giá trị dẫn xuất từ một truy vấn. e.startDate from Event e ". Tất cả các loại kết hợp đều có loại tương ứng trong SQL.

Date startDate = (Date) row[1]. bởi vì một List không thể chứa các giá trị kiểu cơ bản. không có giá trị thuộc kiểu cơ bản (gồm các kiểu như int. Phần sau sẽ trình bày về các hàm tập hợp (aggregate functions) có sẵn trong HQL và cách chúng được sử dụng trong mệnh đề SELECT và WHERE. như hàm now() hoặc CURRENT_TIMESTAMP. avg (tính trị trung bình). Array chứa các thực thể thuộc kiểu Object. giữ các giá trị trong câu truy vấn. // … } Lưu ý rằng các giá trị trong array Object[] có thứ tự giống với thứ tự các thuộc tính trong câu truy vấn. Khi duyệt trên danh sách kết quả. Giới hạn này cũng vẫn tồn tại khi truy vấn một giá trị đơn. Date). e. ta sẽ cần một danh sách cho các đối tượng giản lược.next(). Các hàm vô hướng thường xử lý trên một giá trị đơn và trả về một giá trị đơn. boolean…) có thể được trả về từ một truy vấn dạng này. Cũng có các hàm vô hướng không cần đối số. max (tính trị lớn nhất) và sum (tính tổng các giá trị). Một cách thông dụng để xử lý vấn đề này là dùng các đối tượng giản lược (summary object) chứa một tập con dữ liệu của đối tượng. long. Dĩ nhiên class EventSummary phải có một constructor tương ứng với constructor được sử dụng trong câu lệnh HQL: EventSummary(String. trả về một giá trị được tính toán.list().startDate) from Event e Danh sách kết quả sẽ được trả về theo các thực thể của đối tượng EventSummary. min (tính trị nhỏ nhất). cả hai đều trả về thời gian của hệ thống (timestamp).List results = query. String name = (String) row[0].iterator(). i.name. Hibernate hỗ trợ năm hàm tập hợp trong SQL thông dụng nhất. Trong SQL có hai kiểu hàm: hàm kết hợp và hàm vô hướng (scalar). Xét ví dụ sau: SELECT COUNT(e) FROM Event e Ví dụ này trả về số đối tượng Event có trong cơ sở dữ liệu. Xét ví dụ sau: select new EventSummary(e. Trong trường hợp ví dụ trên. Phần trước đã trình bày về những thành phần chính của câu truy vấn HQL. một đối tượng giản lược sẽ chứa thuộc tính name và startdate của Event. Các hàm tập hợp xử lý trên một tập các giá trị trả về giá trị tổng kết (summary value). Để đếm số đối tượng Event và không đếm trùng các đối tượng giống nhau. Có một cách tốt hơn để giải quyết vấn đề trên. o Trả về các đối tượng mới Mệnh đề SELECT có thể được sử dụng để tạo ra các đối tượng mới.) { Object[] row = (Object[]) i. Các hàm này có chức năng tương tự như các hàm tương ứng trong SQL. sử dụng từ khóa distinct: SELECT COUNT(DISTINCT e) FROM Event e . for (Iterator I = results. gồm: count (đếm phần tử trong tập hợp thỏa ràng buộc).hasNext(). o Sử dụng các hàm Các hàm là các lệnh đặc biệt.

Set attendees = event.payment p WHERE p.attendees where e.setParameter(“name”.get(0). Class Payment xác định cách Attendee sẽ trả tiền cho các Event. Có một cách khác ngắn hơn nhiều để đạt được tập hợp con.attendees a WHERE e. nếu có một class với thuộc tính id được đặt tên là objectId.CashPayment . Bất kể ta đặt tên cho thuộc tính id trong đối tượng và trong định nghĩa ánh xạ là gì thì sử dụng id trong câu truy vấn HQL vẫn sẽ trả về giá trị khóa chính.attendees) FROM Event e WHERE e. Hiện nay để lấy được thông tin này thì code sẽ như sau: String query = “from Event e inner join fetch e.Tất cả các hàm tập hợp đều trả về một đối tượng Integer. Thuộc tính id cho phép truy xuất đến giá trị khóa chính của một đối tượng trong cơ sở dữ liệu. Điều này đặc biệt có ích khi ta ánh xạ một phân cấp class trong cơ sở dữ liệu và chỉ muốn trả về các class thuộc một kiểu xácđịnh.list(). Nếu sử dụng phép kết hợp trong mệnh để FROM. ta có thể sử dụng alias trong phép kết hợp làm đối số của hàm.name =: name Các hàm cũng có thể được sử dụng trong mệnh đề WHERE. Hibernate cung cấp hàm elements(…) để trả về các thành phần của một tập hợp: SELECT elements(e. Xét một ví dụ khác: lấy tập hợp những người tham gia (Attendee) cho một sự kiện cho trước. ta vẫn có thể sử dụng thuộc tính id trong câu truy vấn HQL: FROM MyObject m WHERE m.createQuery(query).name = :name”. Có thể xem thuộc tính Id của HQL như một cách viết gọn cho giá trị khóa chính. Thuộc tính class cung cấp chức năng tương tự. Để truy xuất kết quả.name = :name Câu truy vấn trả về một đối tượng List chứa các thực thể Attendee ứng với sự kiện Event. Câu truy vấn sau sẽ truy xuất được tất cả Attendee trả bằng tiền mặt: FROM Attendee a JOIN a. Thuộc tính class giúp truy xuất đến tên class Java của các đối tượng trong cơ sở dữ liệu. Query q = session.close().get(0). Ví dụ. q. Event event = (Event) q. HQL hỗ trợ hai thuộc tính đối tượng: id và class. Câu truy vấn sau cũng tương đương với câu trên: SELECT elements(a) FROM Event e JOIN e. o Các thuộc tính có sẵn của HQL Các thuộc tính có sẵn của HQL dành cho các đối tượng trong câu truy vấn. Xét ví dụ sau để thấy thuộc tính class được sử dụng như thế nào.id > 50 Ta vẫn có thể sử dụng thuộc tính objectId nếu muốn. Payment có hai class con (subclass): CreditCardPayment và CashPayment. cách đơn giản nhất là lấy giá trị đầu tiên trong danh sách kết quả: Integer count = (Integer) session.class = de.find (“select count(distinct e) from Event e”).laliluna. Ví dụ class Attendee có quan hệ với class Payment. ”Meeting”).getAttendees(). session.

p. mỗi thành phần đóng một vai trò khác nhau và ảnh hưởng lẫn nhau. Các thuộc tính id và class có thể được sử dụng trong mệnh đề SELECT và WHERE.String. các biểu thức hỗ trợ hầu hết các toán tử thông dụng trong SQL. Người phát triển chỉ cần biết các class ánh xạ từ cơ sở dữ liệu bên dưới mà không phải làm việc với các bảng (table). Thuộc tính class chỉ có trong phân cấp đối tượng. thuộc tính class là môt thực thể java. có giá trị là giá trị được xác định trong thuộc tính discriminor-value (tạm dịch là giá trị phân biệt) trong định nghĩa ánh xạ.1 Mô hình MVC trong ứng dụng web MCV (Model View Controller) là tên một phương pháp chia nhỏ một ứng dụng thành ba thành phần để cài đặt.Cũng giống như thuộc tính id. ta cũng có thể trả về thuộc tính class trong lệnh SELECT SELECT p. . đó là models.class FROM Payment p.id. Thay vào đó. 2 Spring MVC 2. và controllers. Nếu truy xuất thuộc tính class của một đối tượng không có discriminator-value sẽ nhận ngoại lệ QueryException báo rằng bộ phân tích truy vấn (query parser) không thể phân tích được thuộc tính class này. o Sử dụng biểu thức Các biểu thức được sử dụng để truy vấn các đối tượng có thuộc tính thỏa mãn các tiêu chuẩn xác định.lang.lang. thuộc tính class không được trả về như là một thực thể của java. Câu truy vấn trả về tất cả các id và class cho đối tượng Payment trong một đối tượng List gồm các phần tử là array Object[]. Được sử dụng trong mệnh đề WHERE của truy vấn. views.Class. Tuy nhiên. Tóm lại: Hibernate là một công nghệ mới giải phóng cho người phát triển code khỏi cơ sở dữ liệu quan hệ thực sự bên dưới. Nói cách khác là thuộc tính class chỉ có trong các đối tượng được ánh xạ với một discriminator-value.

hay ngắn hơn là Spring. sửa. Thông thường. tìm kiếm và làm các thao tác khác đối với dữ liệu trong hệ thống. ví dụ như các dữ liệu được lưu trong database. file system.2 Giới thiệu về Spring framework Spring Framework.  Controllers (Tầng điều khiển): chịu trách nhiệm xử lý các tác động về mặt giao diện. Spring Framework cung cấp các giải pháp cho nhiều thách thức kỹ thuật mà các nhà phát triển phần mềm Java và các tổ chức muốn tạo ứng dụng dựa trên nền . mail system …  Views (Tầng giao diện) : là phần giao diện với người dùng. hộp đối thoại. chọn lựa …. nút bấm.. xóa. là một cấu trúc dùng để xây dựng chương trình ứng dụng mã nguồn mở dành cho ngôn ngữ lập trình Java. để người dùng có thể thêm. Models (Tầng dữ liệu): là một đối tượng hoặc một tập hợp các đối tượng biểu diễn cho phần dữ liệu của chương trình. 2. Trong kiến trúc MVC. dữ liệu từ một hệ thống các ứng dụng khác như legacy system. và cuối cùng là chọn một view thích hợp để hiển thị ra màn hình. view chỉ có tác dụng hiển thị giao diện mà thôi. cung cấp các menu. các thông tin cần hiển thị được lấy từ thành phần Models. các thao tác đối với models. còn điều khiển dòng nhập xuất của người dùng vẫn do Controllers đảm trách. bao gồm việc hiện dữ liệu ra màn hình.

tảng Java phải đối mặt với Java platform. Bởi vì số lượng lớn chức năng của Spring Framework. Thông thường Bean được định nghĩa trong file cấu hình XML 2.Ví dụ: Có thể cấu hình properties. Đối tượng được tạo bởi khung này được gọi là đối tượng được quản lý hay Bean.2. nổi tiếng của nó. vượt lên khỏi các mô hình lập trình từng chiếm vị trí ưu thế trong lịch sử ngành công nghiệp phần mềm. constructor bằng XML: . cấu hình các đối tượng bằng cách nối nó lại với nhau. Tiếp theo. việc phân loại những bộ phận cơ bản kiến tạo nên bộ khung là một việc rất khó. Bộ khung Spring được coi như thực thi một cách làm việc dựa trên những thói quen thực hành tốt nhất và những tiêu chuẩn công nghiệp. có khi còn vượt cả ra bên ngoài nền tảng Java nữa. gọi các hàm khởi tạo. cung cấp một mô hình nhất quán và làm cho nó có thể áp dụng vào hầu hết các loại ứng dụng được tạo trên nền tảng Java ngày nay. Khung này có nhiệm vụ quản lý vòng đời của đối tượng: tạo đối tượng.2 DI(Dependency Injection) Là một mẫu hình mà trong đó khung chứa truyền giao các đối tượng cho nhau bằng tên của chúng. và đồng thời tạo cơ hội cho những lĩnh vực trong Java sử dụng nó 2. Thành quả của việc này là nó đã tạo nên một bộ khung. thông qua những phương pháp khởi tạo (constructor). nó cũng được ghi nhận về việc đưa các chức năng vốn ít được quen biết vào thực tế.1 IoC(Inversion of Control) Cung cấp khung để cài đặt và quản lý các đối tượng Java.2. Spring Framework không chỉ được liên kết riêng biệt với Java Enterprise platform mặc dù sự tích hợp sâu của Spring trong Java EE là một yếu tố quan trọng cho sự phổ dụng. các đặc tính (properties) hoặc các phương pháp chế xuất (factory methods / Factory method pattern). Có lẽ Spring Framework nổi tiếng nhất với sự cung cấp một cách hiệu quả các tính năng cần thiết để tạo ra các ứng dụng thương mại phức tạp.

org/schema/beans/spring-beans.<?xml version="1. không như các system error.springframework. Spring Web MVC cho phép chúng ta sự dụng vài đối tượng như là một lệnh hoặc đối tượng form – không cần implementmột framework-specific interface hoặc base class. view resolution. không cần phảigõ các chuỗi vào trong form đối . ví dụ AbstractController.springframework. Hanler mặc định rất đơn giản “Controller interface”.org/2001/XMLSchema-instance xsi:schemaLocation=" http://www. AbstractCommandController andSimpleFormController.w3. Chú ý rằng chúng ta có thểchọn một lớp cơ sở nếu chúng ta không có một form. vớiviệc cho phép cấu hình các handler mapping.org/schema/beans http://www. sự nhất quán. nó đối xử các kiểukhông hợp như là các validation error. Spring's data binding có tính mềm dẻo cao: ví dụ. Các controller của ứng dụng sẽ là các lớp con tiêu biểu của chúng . nhưng sẽ thích hơnkhi bao gồm kiến trúc thực thi có thứ bậc. Vớitất cả nhửng điều này có nghĩa là chúng ta không cần sao chép các property của đối tượng bussiness.xsd"> <bean id="springQuizMaster" class="SpringQuizMaster"> </bean> <bean id="strutsQuizMaster" class="StrutsQuizMaster"> </bean> <bean id="quizMasterService" class="QuizMasterService"> <property name="quizMaster"> <ref local="springQuizMaster"/> </property> </bean> </beans 2.nó gửi các request đến các handler.org/schema/beans" xmlns:xsi=http://www.springframework. chỉ đưa ra một phương thức ModelAndViewhandleRequest(request. Đây là điều khác biệt chínhso với Strusts. chúng ta không cần một form controller. Cái này đã có thể được sử dụng cho các controller của ứng dụng.response).0" encoding="UTF-8"?> <beans xmlns="http://www. locale and theme resolution như là sự hỗ trợ tốt nhất choviệc upload file. điều này có thể được ước lượng bởi ứng dụng.3 Giới thiệu về Spring MVC Spring's Web MVC framework được thiết kế xung quanh một DispatcherServlet t.

nó cho phép các công nghệ view hoàn toàn trừu tượng. hoặc qua thông ViewResolver implementation của chúng ta.4.tượng chỉ để xử lí yêu cầu không phù hợp. nhưng chỉ làmcác thuộc tính bean cho các lớp Action tương ứng. Thay vào đó nó thường đưa ra sự liên kết trực tiếp đến đối tượng business của chúng ta. được thiết kế xung quanh một servlet trung tâm. và một mô hình để thông đến view. một WebWork Action kết hợp tất cả những vai trò đóvào trong một đối tượng riêng rẽ. Với những thứ như vậy. Thật sự. chứa đựng dữ liệu liên quan). Như vậy.1 DispatcherServlet Spring's web MVC framework giống như nhiều web MVC frameworks. làm nhiều hơn là chỉ có vậy. Mô hình sẽ đơn giản bao gồm lệnh và đốitượng form nhưng cũng có dữ liệu liên quan tùy ý. người ta có thể cho rằng có quá nhiều vai trò cho mộtđối tượng. môhình (Min MVC) được dựa trên Map interface. Một vài renderer có thể được tích hợp trực tiếp. những thể hiện Action giống nhau. nó gửi các request đến các controller và đưa ra những chức năng dễ dàng cho sự phát triển củaứng dụng web. Mô hình Map được chuyển đổi một cách đơn giản thành một địnhdạng thích hợp. sự xử lí request của nóđược sử dụng cho việc đánh giá và xũa định vị trí của form trong View. như là JSP. Cuối cùng. dữ liệu liên quan cũng cần được môhình như các thuộc tính bean của Action.4 Một số thành phần quan trọng trong Spring MVC 2. Trong trường hợp đơn giản.So sánh với WebWork . spring có thêm các vai trò khác của đối tượng.một lệnh tùy chọn hoặc một đối tượng form. requestdriven. một file properties. Spring DispatcherServlet bất cứ như thế nào . 2. Thay vào đó. như là các thuộc tính JSP request hoặc một mẫu Velocity. Nó hoàn . nó chứa đựng tên bean và những đối tượngtương ứng (going một lệnh hoặc một form. Giải pháp dùng tên view có thể được cấu hìnhtốt. Nó hỗ trợ thể sự thông báo của một controller. WebWork cho phéo chúng ta sử dụng những đối tượng business của form. hoặc thông qua tên bean. hoặc chuyển đổi thành các chuỗi. Strust được xây dựng xung quanh yêu cầu các lớp cơ sở như là Action và ActionForm. Một sự thực thi của một Controller có thể thậm chi có thể ghi một view trựctiếp vào response ( bằng cách trả về giá trị null null cho ModelAndView). một thể hiệnModelAndView bao gồm một tên của view và một mô hình ánh xạ( Map). Đậy là điểm khác biệt chính so vớiStruts. Velocity….

xml của ứng dụng web của chúng ta.springfra ework. Người đọccó hiểu biết về mô hình sẽ nhận thấy rằng that the DispatcherServlet là một sự diễn tả của mẫu thiết kế “Front Controller”(đây là một mẫu mà Spring Web MVC chia sẽ với nhiều web frameworks dẫn đầu khác ) DispatcherServlet là một Servlet thật (nó kế thừa từ lớp cơ sở HttpServlet ).serv et.toàn được tích hợpvới Spring IoC container và như vậy cho phép chúng ta sự dụng bất cứ đặc tính nào mà Spring có. Đây là chuẩn cấu hình của J2EE servlet. Những request mà chúng ta muốn DispatcherServlet xử lí sẽ được ánh xạ. một ví dụ như là một sự khai báo của DispatcherServletvà mapping có thể được tìm thấy bên dưới.DispatcherServ et</serv etc ass> < oad-on-startup>1</ oad-on-startup> </serv et> <serv et. sử dụng một URLmapping trong cùng file web. Luồng xử lí request của Spring Web MVC DispatcherServlet được minh họa trong lược đồ bên dưới.xml. <web-app> <serv et> <serv et-na e>exa p e</serv et-na e> <serv etc ass>org.web. và như vậy được khai báo trongweb.apping> <serv et-na e>exa p e</serv et-na e> .

. tìm kiếm một tên file [servlet-name]-servlet. Bây giờ..for </ur -pattern> </serv et. Framework sẽ. Đây chỉ là bước khởi đầu để cấu hình trong sự thiết lập Spring Web MVC.<ur -pattern>*. trên sự khởi tạo của một DispatcherServlet.xml trong thư mục WEB-INF của ứng dụng web của chúng ta và tạo các bean được định nghĩa ở đó (overriding những sự định nghĩa của một vài bean đượcđịnh nghĩa cùng tên trong phạm vi global).apping> </web-app> Trong ví dụ trên.Những bean khác nhau được sử dụng bởi Spring WebMVC framework (trên và DispatcherServlet trên của chính nó) cầu được cấu hình ngay. chỉ như một vài bean khác cần được cấu hình.form sẽ được xử lí bởi 'example' DispatcherServlet. vừa để chúng ta biết chúng . Spring DispatcherServlet có một sự ghép nối với các bean đặc biệt. Những bean đó được bao gồm bên trong Spring framework và có thể được cấu hình trong WebApplicationContext. chúng ta sẽ chỉ đề cậpđến chúng. Mỗi cái bean này được mô tả chi tiết hơn bên dưới. tất cả các request kết thúc với . nó dùng để có thể xử lí các request và tạo ra những viewthích hợp.

vìthế nếu chúng ta không cần locale giải quyết . Vị trí của locale resolver được bao với request để các nguyên tố trong trong quá trình xử lí giải quyết locale để sử dụngkhi xử lí request (tạo view. cho lí do bảo mật).8. (XemSection 13.v. “Using the MultipartResolver” thêm thông tin về multipart handling). từ khi request có thể đã được đầy đủ Những ngoại lệ được quăng ra trong quá trình xử lí request nhận được một cách tình có bởi một vài handler exception resolver màchúng được khai báo trong WebApplicationContext.or postprocessor. Hầu hết các bean. có thể thấyđược mặc định được cung cấp vì thế chúng ta không (initially) phải lo lằng về làm sao cấu hình chúng. nếu các multipart được tìm thấy.tồn tại và có thể cho phép chúng ta nói về DispatcherServlet. 5. Theme resolver được bao với request để các yếu tố như là các views xác đinh theme nào được sử dụng. Nếu một multipart resolver được đặc tả.2. 2. Themeresolver không ảnh gì cả nếu chúng ta không dùng nó. vì thế chúng ta không cần theme thì chỉ cần chúng ta làm ngơ với nó. không có view được phát sinh (render). chúng ta không phải xử dụng nó. view được phát sinh (render). WebApplicationContext được tìm kiếm và bao trong request như một thuộc tính để cho controller và những nguyên tốkhác trong quá trình xử lí sử dụng. Nếu một model được trả về. phân hoạch request. các postprocessor. Nếu một handler được tìm thấy.Spring DispatcherServlet cũng hỗ trợ trả về last-modification- . Sự dụng những exception resolver đó cho phép chúng ta định nghĩa những hành vimột cách tùy biến trong trường hợp như các exception có được bởi sự quăng ném. nó sẽ không gây ảnh hưởng gì cả. 3. sự xử lí buộc liên kết với handler (cácpreprocessor.. và controller) sẽ được thực thi để chuẩn bị một a model (cho sự phát sinh [render]). chuẩn bị dữ liệu. Nó được bao mặc định bởi khóa DispatcherServlet.) nếu chúng ta không sử dụng resolver. người ta bảo rằngDispatcherServlet bắt đầu xử lí các request.WEB_APPLICATION_CONTEXT_ATTRIBUTE. Một handler thích hợp được tìm kiếm. 6. Khi một DispatcherServlet được cài đặt cho việc sử dụng và một request đến DispatcherServlet đặt biệt. requestđược bao phủ trong một MultipartHttpServletRequest cho quá trình xử lí xa hơn nữa bởi các yếu tố bên trong xử lí.v. request được duyệt cho các multipart. Danh sách các mô tả sau mô tả đầy đủ một request đến khi được sử lí bởi mộtDispatcherServlet: 1. ví dụ. 4. Nếu không có mô hình nào được trả về (cái có thể được quy vào một pre.

các command-based controller. Controller interface định nghĩa một phương thức đơn độc chịu trách nhiệm cho việc xử lí một request và trả vềmột model và view thích hợp. public interface Controller { /*** Process the request and return a ModelAndView object which the DispatcherServlet* will render.ModelAndView và Controller. Source code cho nó đượcliệt kê bên dưới. Các Controller cung cấp chế độ truy cập vào ứng dụng mà nó được định nghĩa tiêu biểu bởi một service interface.2 Controllers Sự thông báo của một controller là một phần trong thiết kế của mô hình MVC (Chính xác hơn nó là 'C' trong MVC. và các controller mà nó thực hiện wizard-style logic. 2. } Như chúng ta có thể thấy. 2.web.date. Spring đưa ra một lượng các Controller implementation có thể sử dụng dễ dàng và nó đãchứa đựng một lượng các chức năng mà chúng ta cần. Springchứa đựng đặc tả form (form-specific) của các controller.4. Nếu thế. Tiến trình của sự xác địnhngày chỉnh sửa cuối cùng cho một request đặc biệt thì không phức tạp: DispatcherServlet sẽ tìm kiếm một handler mapping thích hợp và kiểm thử nếu handler được tìm thấy interface implements the interface LastModified .Controller interface chỉ định nghĩa yêu cầu trách nhiệm cơ bản cho mỗi controller. Trong khiController interface là khá trừu tượng.springframework. Ba khái niệm đó là cơ sớ cho Spring MVC implementation . thành tên nhưng một ít. giá trị của phương thứcgetLastModified(request) của interface LastModified được trả về cho client.4. cho phép một lượng lớn các loại controller được tao tạo ra.là xử lí một request và trả về một model và một view. Kiến trúc controller là interface org.Controller.HttpServletResponse response) throws Exception.*/ ModelAndView handleRequest(HttpServletRequest request.3 Handler mappings . Spring đã thực thi sự thôngbáo của một controller trong một cách chung chung trừu tượng.mvc. như là được đặc tả bởi Servlet API. Các Controller giải thích user input và chuyển đổi thành dạng input có thể hiểu được mà nó sẽ được trình diễn cho user bằng view.servlet.

Nếu thuộc tính này được set là false (mặc định). Khi handler mapping này không hợp với handler nào. Nó cần chứa handler phùhợp với request. chúng ta phải đặt thuộc tính này là true (nó yêu cầu JDK 1. Defaultvalue is false .the HandlerInterceptor interface”.Sự dụng một handler mapping chúng ta có thể ánh xạ một web request đến một handler thích hợp.4). Nếu chúng ta không muôn chúng được mã hóa trước khi HandlerMapping sự dụng chúng để tìm một handler thíchhợp .html sẽ được sử dụng. Cách xử lí của một handler mapping tùy ý là một handler không chị dựa trên URL của request mà nócũng mô tả trạng thái của session liên kết với request. • urlDecode: Giá trị mặc định của thuộc tính này là false. hoặc cả hai) là thực sự mạnh mẽ. Sau đó DispatcherServlet sẽ thực thi handler và các bộ chặn trong chuỗi thực thi (nếu có). • defaultHandler: default handler để dùng. Phần này mô tả hai handler mapping thông dụng. /viewPage. Có một vài handler mappingchúng ta có thể sử dụng một cách tự nhiên. Nếu một servlet được ánh xạ sử dụng /testing/* và alwaysUseFullPath được set là true.html sẽ được sử dụng. • order: dựa trên giá trị của thuộc tính order (xem org. Khỗi lượng các chức năng được hỗ trợ có thể được xây dựng trong việc xây dựngcác HandlerMapping tùy ý. Ví dụ. Chúng mở rộng từ AbstractHandlerMapping và cùng có những thuôc tính sau: • interceptors: danh sách các bộ chặn để dùng.Ordered interface).core. Chúng ta không nên thay đổi giá trị mặc định. Spring sẽ sắp xếp tất cảcác handler mappings đang có trong context và áp dụng handler đầu tiên. Khái niệm configurable handler mappings là có thể tùy ý chứa đựng các bộ chặn (thực thi trước khi và sau khi handler thực sựđược thực thi. Chức năng của một HandlerMapping cơ bản cung cấp là sự phân phối của một HandlerExecutionChain. đường dẫn bên trong servlet mapping hiện tại sẽđược sử dụng . Spring sẽ sự dụng đường dẫn đầy đủ servlet context hiện tại đểtìm handler thích hợp.springframework. Phương thức decode sử dụng hoặc là encoding được đặctả bởi request hoặc default ISO-8859-1 encoding . Trái lại nếu thuộc tính được set là false. và cũng có thể chứa đựng một danh sách các handler chặn mà được áp dụng cho request. HttpServletRequest trả về request URLs và URIs mà không đượcdecoded. “Intercepting requests . Xem thêmSection 13. Bình thường. chúng ta có thể sử dụng UrlPathHelper khi kiểm tra URLs. ví dụ: SimpleUrlHandlerMapping hoặc BeanNameUrlHandlerMapping. • lazyInitHandlers: allows for lazy initialization of singleton handlers (prototype handlers are always lazily initialized).DispatcherServlet sẽ điều khiển nó thông qua handler mapping để phân tích và kiểm tra request và mang lên với mộtHandlerExecutionChain thích hợp.3. • urlPathHelper: sử dụng thuộc tính này.4./testing/viewPage. Khi một request vào. alwaysUseFullPath: nếu thuộc tính này được set là true.

view.web.2.5 Hoạt động của Spring MVC - Dispatcher Servlet nhận request Dispatcher Servlet sẽ dựa vào HandlerMapping và gọi Controller tương ứng với request .springframework.UrlBasedViewResolver"> <property name="prefix" value="/WEB-INF/jsp/"/> <property name="suffix" value=".4 Một số thành phần khác  HandlerAdapter:Thực thi đối tượng nắm giữ yêu cầu đến  View: trả về response tới client  ViewResolver: tất cả các MVC framework đều cung cấp resolver để định vị view. và tùy chọn lưu cục bộ của một người dùng cá nhân MultipartResolver: tạo điều kiện thuận lợi cho làm việc với các tập tin tải lên bằng cách gói yêu cầu gửi đến 2.4. Spring cung cấp view resolver dùng để render mô hình trong browser mà không cần buộc đến view cụ thể.servlet.jsp"/> </bean>  HandlerInterceptor: chặn các request đến. <bean id="viewResolver" class="org. không được điều khiển bởi DispatcherServlet  LocaleResolver: giải quyết.

Controller thực thi và trả về đối tượng ModelAndView cho DispatcherServlet. Servlet đã tạo 1 sự khác biệt rất lớn cho các nhà phát triển Web bằng CGI vì servlet mạnh mẽ và hiệu quả hơn. Điều này gây khó khăn trong việc duy trì mở rộng code. response.DispatcherServlet sẽ gửi tên của View cho View Resolver để tìm View thật sự. 3. Để đối phó với khó khăn này. . đọc XML…. nhưng sẽ gây khó khăn cho những người chưa có kinh nghiệm nhiều trong Java. giải pháp này lại có một thiếu sót của riêng nó: mã Java nhúng trong HTML sẽ dẫn đến sự phức tạp trong các trang JSP. Tuy nhiên. các nhà lập trình đã chỉ ra rằng servlet có một thiếu sót hết sức quan trọng đó là các nhà phát triển web tạo ra giao diện về phía client bằng cách xuất ra các đoạn code HTML thông qua câu lệnh print. Sự kết hợp giữa Expression language và thư viện tiêu chuẩn toàn diện. JavaServerPages Standard Tag Library (JSTL) được sinh ra.1 S àg JSTL bao gồm các phần sau: Expression Language Thư viện các hành động tiêu chuẩn Thư viện cho validation Expression Language được cho là tính năng quan trọng nhất của JSTL. Hơn nữa.2 Các th viện th của S Thư viện thẻ của JSTL được chia làm 4 loại như sau: n th viện prefix M t . sự kết hợp code business logic và presentation làm cho trang JSP trở nên khó hiểu và khó duy trì. các biến liên quan đến scope Thư viện các hành động tiêu chuẩn cung cấp một nền tảng vững chắc cho việc lập trình web từ việc lập vòng lập. Điều thiếu sót này nhanh chóng được khắc phục bằng JSP cho phép nhúng các đoạn code Java. Expression Language cho phép truy xuất vào các implicit object như request. import URLS đến kết nối database. việc chỉ giới hạn trong một số thẻ tiêu chuẩn như <jsp:useBean> hay <jsp:include>. ModelAndView chứa Model và tên của View . JSP có thể tốt cho những người phát triển Web thông hiểu Java. như trong hầu hết các trường hợp.DispatcherServlet sẽ gửi Model cho View để render ra kết quả cuối cùng và trả về cho user 3 JSTL (JSP Standard Tag Library) Vào năm 1997 Sun Microsystems giới thiệu các API Servlet. Tuy nhiên khi đưa vào áp dụng. rất nhiều custom tag được tạo ra ví dụ như Jakarta Taglibs được tạo ra bởi Apache Software Foundation Từ sự phát triển của Jakatar Taglibs và những phản ứng tiêu cực khi phát triển web trên JSP. JSTL đã tận diệt sự cần thiết phải dùng scriptlet và expression trong trang JSP 3. các nhà phát triển Java lợi dụng một ưu điểm của Java là cho phép tạo ra các custom tag.

1 Core ction g các chức n ng sau Send output to the current JspWriter Gửi output đến JspWriter hiện tại Thao tác trên các thành phần của Java Bean Triển khai statement if hay switch Xử lý các Exception Duyệt qua các mảng giá trị. forEach…. Người lập trình có thể: Xác định resource bundle cho các thông báo với nhiều ngôn ngữ Xác định khu vực để định dạng ngày tháng. Formatting (fmt) Định dạng và quốc tế hóa SQL (sql) Truy xuất CSDL XML (x) Phân tích và đọc dữ liệu từ XML 3.2. chuỗi Tạo các URLs và import tài nguyên Redirect servlet responses Chuyển các trả lời của Servlet Tạo và hủy các biến trong scope Các Action trong Core: Tên Action nghĩa <c:catch> Catch những exception xảy ra trong code body <c:choose> Chọn 1 trong nhiều đoạn mã để thi hành khi thỏa mãn điều kiện nào đó <c:forEach> Vòng lặp quét hết tập hợp nào đó <c:forToken> Vòng lặp quét hết 1 chuỗi nào đó theo chuỗi phân cách <c:if> Thi hành đoạn code khi thỏa mãn điều kiện <c:import> Import một URL nào đó <c:otherwise> Xác định giá trị mặc định cho <c:choose> <c:out> Gửi output cho JspWriter hiện hành <c:param> Xác định 1 tham số URL cho <c:import> hay <c:url> <c:redirect> Điều hướng request sang URL mới <c:remove> Xóa 1 đối tượng trong 1 scope nào đó <c:set> Tạo 1 đối tượng trong 1 scope nào đó <c:url> Tạo 1 URL <c:when> Khai báo điều kiện trong <c:choose> 3. phần trăm Các Action trong Formatting Tên Action nghĩa <fmt:bundle> Xác định resoure bundle cho các messge đi kèm trong thẻ - . tiền tệ.Core (c) Chứa các hành động cơ bản như if.2 Formatting Action: JSTL formatting Action cho phép người lập trình quốc tế hóa trang web của mình.2.

bạn nên tìm hiểu những nguyên tắc thiết kế của JSTL. Trong nhiều trường hợp nếu bạn khai báo giá trị null hay chuỗi rỗng cho thuộc tính.fmt:bundle <fmt:setBundle> Xác định resoure bundle và gán vào 1 biến để dùng sau này <fmt:formatDate> Định dạng ngày theo 1 vùng địa lý nào đó <fmt:formatNumber> Định dạng số theo 1 vùng địa lý nào đó <fmt:message> Truy xuất vào 1 message trong bundle 3. thông tin được truyền từ trang JSP vào code Java và ngược lại.1 ui ớc đ t t n Tên thẻ và tên thuộc tính của thẻ được đặt tên theo qui ước đặt tên của Java: qui tắc Lạc Đà. Thông qua ống dẫn này.amount}'/> <c:forEach var='item' items='${names}' varStatus='status'> 3. các từ tiếp theo được viết hoa đầu từ.3 guy n t c thiết kế Để tận dụng tốt nhất của JSTL.3.3. giá trị đó sẽ được chuyển đổi thành các hằng số vô hại ( như “0” ch ng hạn) 3.3.3 Các thuộc t nh động Giá trị của các thuộc tính trong JSTL có thể tĩnh hoặc động. trang JSP sử dụng thẻ <c:forEach> để gửi thông tin qua giá trị của biến “var” cho class tag handler. Scripting Variables Các thẻ JSTL như là một ống dẫn giữa trang JSP và mã code của Java. các nguyên tắc này áp dụng đối với nhiều thẻ trong JSTL nhưng không phải tất cả. Class tag handler tạo ra 1 đối tượng “item” như là một biến cục bộ cho thẻ <c:forEach> 3. Ví dụ: <c:out value='${param.3. từ đầu tiên là chữ thường. Giá trị của thuộc tính động có thể được xác định thông qua các Expression Language (EL) 3.4 h General-Purpose and Conditional - .2 Scoped Variables vs. Hãy xem xét ví dụ sau đây: <c:forEach var='item' begin='1' end='10'> value = <c:out value='${item}'/><br> </c:forEach> Trong đoạn mã trên. Các nguyên tắc thiết kế thảo luận trongphần này là: Qui ước đặt tên Phạm vi của biến Các thuộc tính động Xử lý lỗi 3.4 i JSTL làm tất cả để tránh xảy ra các lỗi trong quá trình thi hành.

Khi thi hành chúng ta có kết quả như hình sau: Trước khi Submit . các thuộc tính của JavaBean. và dùng <c:out> để xuất giá trị. thực các biểu thức điều kiện và xử lý exceptions Các thẻ General-purpose: JSTL cung cấp 4 thẻ sau cho General Purpose: <c:out> <c:set> <c:remove> <c:catch> Ví dụ: chúng ta làm một ví dụ đơn giản về các thẻ general purpose như sau: - Trong ví dụ trên chúng ta dùng EL để truy xuất vào parameter của request lấy giá trị của “buttonText”. truy xuất và thay đổi giá trị các biến trên các scope.- - - Một số nhiệm vụ cơ bản của các nhà phát triển JSP bao gồm tạo ra output.

5 h Conditiona JSTL cung cấp 4 thẻ cho Conditional: <c:if> <c:choose> <c:when> <c:otherwise> Ngoài ra JSTL còn cung cấp thêm 2 thẻ cho vòng lặp là <c:forEach> và <c:forToken> Ví dụ: chúng ta làm ví dụ kết hợp các thẻ trên với nhau như sau: Đầu tiên chúng ta hiển thị kết quả từ vòng lặp: - - Khi trang web chạy lần đầu chúng ta cho phép người dùng nhập vào các giá trị cần thiết cho vòng lặp .Sau khi submit 3.

chúng ta xuất thông báo lỗi như sau: - Khi thi hành chúng ta có kết quả sau: .- Trong trường hợp người dùng nhập vào các giá trị không đúng.

- Khi nhập liệu sai định dạng chúng ta có thông báo sau: .

3.02.$.0 88.943995.02..4. 389.

.

2047 47. 857317.

02.8.

-0.38 995.

.

 857317.2047 47.

02.8.

38.-0.

8573 -0.8907 .88$573":..38 8/ -0.3/8573":.8907.

-0.8907.88$97:98":.3/897:98":.3 -0.8907 ..

.-0.8907$07.8907 7014.8907.206:.3 -0...0.88":.3/6:.8907$07.0 57450793..8573":.

 .

5745079 .

-0.3 .

O9.E.80.38      9:.  9.3 29 1472 . -9 .E.O29 1472  .3 9..3295.9.. 3 79 ..8/3...O9 -.O9 ..O9 .389J. 4/03/'0.099 3O .2934. 3 .0..E..38..4397407  l  : E..9.O9J322/4. 9.3.3-3/3 33.E.3/$2504724397407  E.0 7084:943 4.2047 .325020392917.  9.31472 3...3.88  $573 8/.1.39. .3 9.4.E. 8890207747 '99.43 9H: -: ..39.3 -:883088  3 .307 2.83:.: .39071. 5 ./..4397407.$573' $573 80-'17.4397407 . 3 /3 8  .J / -897.J384 .E.706:089 3.4.E.553 ..42397.E..O3..3 3 4397407 39071.4 .:54.. 5745079 .33.07$07.32985.9422.J/ 3O .3-....3/90207084:9433.99:36:.9. $97:898  $5730-'.-0.3  73.45F5.-3/3..3/07 ..8/3.4.3/4397407 ....:K3..3 5 .8979939.33 :3.04.94397407  -897./10  .. . ..0  .39..4 9743 1472  .E.3/072.3/3 3..3/0#06:089 706:089 70854380 E3 . .2047 850.9.F5.:353..39.94307747  :3. 29 5.-.45F5..E. 7..  8 39 6:E3  .

35 .429 9.33 432934.07$07.9J3$!706:0894.8/333 9.07$07.2.O992.E.. 33 .9J.20478  706:089 /7.39 %..3 3-.3 O979893-E4.5.5 ....3.0 K38 .4397407 2939 .4 O  29 0-47 .7.943 .3-:83088..703/0707.9.3 /3 0-  $57385. /.. 93 6:.03  .:K399  4.95.O6:E3:. 93 '0#084.. 33 ..9J3-0. 39H3-0..3O .934 23:...9:.39..45F4.9J3-0. 1472 9743 '0  ....3.3 ..0..29 9... 3.94333.95 3.33 29934/03/'0-.943 '3393.4.. l 2E.3 9.. 3g3 / /3 .39.$97:98 $97:89 .97. 9H3 -0. 9.597.E.3-:83088.O929.95 3 9.E.....9     9893536:.9:.E..: 8J706:089. 99  :3 6:. .3  29 10 574507908  4.: %.29 2:'04.4397407 . E3E. JH:.E.3 7H37 0-47... 97H3 .3.E.-9.:3 93. 2K33..33 :...3..9.5 3.9.0-47 8573.44/03/'0 %74397.3 .O.4 8 5E9 973 .4 O3O9.E973:3:.3.3 33 93.. .4 70854380 -3..  %9 8  2K3 3 '  .09  $573 8 0- ' 17.33 9.8H3997.E.314723.:3  29.83.$! '04.4.5 .E.O/:H36:.29 1472 .5 3O. . O43 .5 39071.J384..E.3 29 807.9439. .423.34.9 K3.9.3 .09-9. 7.E.45F5.3. 29..3.:355 4.292K3 93 3.. .339329 3/39J.9:... ..1472  3. 97 O.3 5E5/39H3.8/3. 97E.  / : H3 6:.97.4 9743 29  9.42299H3.294397407. 6:..3.3 9.943 9 5 99 .2047 3 3.292K3 E3  .O 9 . 3 ..31472 .39.473.07 2502039..39739743$573'     85..04394397:9./3:36:.943.O9H2...3.E...0 3O.097. 706:089 3 . 3: 0- ' 17. 3/:H36:.33.O9 .O9 .:.E..0. 97J ...09 97:3 92  3O  .3H:.3 .943472 $48E3.3  989.9. 9.

3:0-17. E3   8 /3 29 &#2.$5734.  0- .9J3342$573. $573 0- ' 85..9.9.3 10 0- 2  l  .39.2.09  29 8 /3 9 .09 29 ..O  :3  J 706:089 .20478/3 :E.943 .09 807.  ..09 29 $07.553 9743 .09..07$07...07$07.9. 2 K3 8 33 9 73 9.-E497430- 2.45F5..3.3/30-.439.8995$07.09 .J / 3. 2:3 85.. 9743 .95.9.3.9 90 85.   85.55 807..09 99 3O 9.07$07.307..O : -9 .39. 3706:0892 .9K29-H3/..5..3 9.09 3..200.. .07$07.-E4.07$07..8.: K3 ..O9 . .9.553.  -H3 /.  807..09  J 8 .85.09  . 2: 99  7439 4397407   29 2:2$5730-'.250. . 23 ..9J.  298..:3 .8/3-9 . .

9.20 807.8847 857317.09 3.2047 0- 807.07$07.807.09 .09 85.09..

09 ../ 43 89.807.79:5.88 4.

/ 43 89.79:5 .4.

250.09 2.200.553 807.807.09 807.09 3.

20 .09 3.807.

99073 1472.:7 5.

:7 5.99073 .

807.09 2.553 .

-0.9.5 3. 14728 .3 .J33O .20478 97H3894.29.3 ... 29 .8.09 9K22299H310 807..42 -H39743 $57317.3 9H3974352.07$07.2.3 .3 E.55  %743.3 O .-0.947.9. .33 . 3 3.99 ..  $57385..J- 0.-.2047 97H3.33 ..09..94343909  . .39..  :  .85.3/30-.. -0.07$07.250  85.3 .O9 .. .3.  .3 E.3 ..:K3 . .-9.: ...:K33..9.  O 4..39.2985.706:089.E.-0.09 3.077/3 33 8 3 3.: .9.: K3 9743 8 99 5 $573 0-' 3-0..5 3-0.3-H3/.29 .8 /3- $5730-'17.0- .J/97H3 99...4-.07$07..0997H3.07$07.E-0.O 298 F53.E.09J..:K397430-55. 3 3.39..09  l .706:08999..  -..09 2 97439..E..E..    7.2047 . .94.3.20( 807...O 9J.-9 3O/3 .3 .

5 .9K3 .O9.4..-..09 .5489574.-.4...943    &83 90 :95.E.4 5 9743 29 :95.9..3 .O9  .4 5F5 .: 2 9   29 706:089 3  .79 3: . -.3.4..0 .39.39. 9.79.0  .9 706:089 .29.E.42. .. 5E9 83 703/07  9  706:089.E.85. 3 /3 3O .05943 7084.-.3/07 .797084. 3 8 /3 7084. 3: .07  3O 8 3  3 . .39.94343909  $ /3 33 0.97436:E97K3J8/3 O .H39.97.429570 475489574.:93.:9-H39743  J  02$0.485E983703/07(     : 29 24/0 .39797..  .4 J /4 -4 29  3 .9.5 ..09#06:089. -E4 9743 0-55. 3 . 8 /3  %0207084..E.706:089 ..3 9.07 .9. .3 . 9 -3 9743 97.9 . 8 /3 .3/07 0. .3.3/079J.09. -..79#084.08847 .07 ../:9..3 9.E.34. 3 3.79995$07.3 9.09 :9. 9K2 2 .E.46:E97K3J.E..K9. 97 .35/33O    %0207084. 3 39.09 -9 :  J .. 2:95.2:95. .:K3.E.07$07.O9 .94343909 .07 2.9. .3O. 9.4.  .9K29 8J -:.08847 .07084. -4 7385.3:H39974397436:E 97K3  J  6:9 4.07$07.39..9.K 9 .45F5.     334 ..0  8 /3  J 706:089 94 .4.3 K .24/0 .07$07.09 *!!% * %%*%%#&%    '97J.07 3 3 K ..23..O9 9 .O .4 .E.07 . 2:95. 2 9 8.3 8E.3/3    9..08E. 3 9020 34 .3O    :292:95..07 9H2 93 93 .:3 . 0..07$07.K93:.:3-29.6:. 2.79 ..39.706:089 .  5 4 3 . 29 9:. 706:089  .4397407.943 ..E.333:H39E. 3-O. .4 9743 706:089 3..3 5 3.06:9 .4397407 8 .07$07.  3: ..J /  .6:g37..O 2 K334 . 706:089  . 8 J - 2985.29 ....85. 9K2 9  706:089 ...05943 .E.....4.3/07 .3.O .E.07$07.3 9.3    29 85.08847 534.9K22 :29..-0.939.E. .E.33.390209K..07 O .97436:E97K3J706:08933 . 9J3 . 28..9. 33 3 . 5E9 83 703/07  : 3 .09    0-55. -.570574. 9 .. ..05943 7084..9.09 9 -9  3.-86:g33F2 $57385.E.0 . 29 706:089 3 85.O - 29 .07$07.:3 - / : .89 24/1.

4947.039071.. :80735:9.2K3' J3 E.. 5 .3 29 J9  3 97.4.4397407  39071..:3.09 !  %3 97K3 .0989K22 29 .439740723O9.:3 .:397:9.9H:-:- 29807.0 E..4397407974329. ....429706:089 .3 9.9585.9.3...23O8 .39071.4397407 ..O9: ..0 47 857317.894/10/ . 33 ..:..422.  . 8 E.7/ 8904.E. .. 5./..4.4397407.E..5.9H-H3/..29.90  3.3 8.:3 93/335:9.1.0. 9 1472 1472 850.5.. 2 9 3: .97K3/3 .33O  9743' E.553 9J.9.-99K35. .2047 0- 807.. .894/10/  : 9  E 97 . 3 .07$07.09 2.894/10/ 706:089 .4397407 9J.  .. . 4397407  $4:7.. 9K2 9 39071...43O .E.3/07 2.4397407  . 33.039      43974078  $93-E4.45F5 29. 97:.43/3 23O .E. ..04397407  .9893-E4.43974072953974399.0 .3/07 .3 .0 $573 9.0.  $573.97.33.4397407 .  5:-... . 939H33.. 9 - $07.3 .3/ -.29.0 25020398 90 39071..09.80/ ..39071..E.4:807-3.4/0.

 !74.9.9 .3/ 709:73 .07$07.09 703/07 . 90 85.088 90 706:089 . 4/03/'0 4-0.

4397407  J 29 706:089 ..4.97.3 .. 4397407 %743439740739071.3/072.3 .39. 32 .0 33. .4 2 .O98/3//3. 4/03/'0 .29.7. 3g3 2 . E 32 O  .. .J29706:089.943  4/03/'0 .3/0#06:089 995$07.E..09J.0E97:9.5 . .:97E....3 4397407 39071.3 9.5538 .0 .09#06:089 706:089 995$07. 29 .E.2924/0.43974072502039. 97 .0      .39. 29 24/0 .32.3 $573 . 295.: 97E.05943 < ..943. 8 . 3 3.3 . .3O .. 329..09#0854380 70854380 9748.O99 439740739071. -3 .... H: .4 $573 ' 2502039.

E.5538 .553..3/072..809 1..706:089 .553.9J33 ..  J . 29 .8/3 'J / :29807... 8 23 2   .9..3  /3  02 9H2$0. 297.5  $.3 .3/07 :9H3  .3.9.J/$250&7.0 $573885599.09 . 8 .4390939 9K2.  97 .-0. 3g3 ...43909.4 85.808843 H39.9 3:.706:08923O.0593706:0898 90.O 9 .0594739071.9:.3/3  807.9J347/07 0247 857317.E.3 .O339:.3/07 2.:943. 29..9J33 .:  .20&7.09. 9.3/079J.3 9.3/073907.553  .E.. .4 706:089   29 706:089 .97H3&#..07$07.3/3-H39743807.3/07  /3   .0989..3/07.O 9 E3  29 0- 706:089 3 29 . E5 /3 ..3H3 .  /3 9743 ..059478 /. 2.0..3/07. 3 29 /.E. .O  E32. 3.:943..553 93 /3  3 2 73 9 -897..9 3H3 . 29 .3/07..3/07 2.5 O29 .07$07..O98/3 29.553 .431:7.553 . . .$ /3 29 .943    3907.5 :9:.3/070.  .5538. .3/07 2.. .80 2.O9743.3/07.5534.3/07 2.. 9  4. .9.706:089  !3 3 2 9 ..092.3/07.E.553 9  E.3299739E.3/0734  W47/07/.: W 3907.553398 .O 9 . - .:9.:3 .553 3 3 5 .553 53 9J.. .8&80:!.3/072.3/07 /01.9J38.-.:9 .098 : 33O936:.0  W /01. .3/07 .3..3/073..2047 .39J. 9 97. 8..3/07 2. .E..E38/3.3/070.5  8 53 5 .O99 .9.3 .E.3/07 9.39743.3 9...3/07 2. ..  /3.470 7/070/ 39071. .-.553 9   29 ..: O85.3 8E. 29 . 3g3 . 706:089  .3 8E.:9.3/079J.80997:0 $57388/3 . .3 2 .3. 3  . -3 .93:9:.   9.3/07 55 ./.E5 /3.3  O .3/07.E.97H3E97.39.

90893.

.8&80:!..809 97:0 . .9 ..

90893.

.8091...0!.9J3 .8/3 %7E3:9:.80  .0 928 .

.5538/3.9J3 31..4/0/  : .:  !.:9$  03.39.03.3/078 57494950 ...0/ 01. &#8 2 3 .3/078.5 99:..8/3  W:7!./01...4/3  W .9:. E972..39.O98/3&7!..70. 3.39.3/07. 39.5  .9J33 . ./0.4/0E97 2.39.3/079J.80 995$07.943 41 830943 .:9.33H39.97./0.4/08 /34.9J3397:0 3OH:.3/078 ..0!.0 928 .:081.3 9K229. 3 2:3 .09#06:08997 . 706:089 &#8 .8..80  .&#8 K39..4/3 .2O.3 9..39.3 39.48 147 . 3  W:70.90507  297.905078/39:.9-706:0894.3 .

   989353E.: 3  '097..332H:.5 .0.3-:..0799.3/07/.708543809.039  '0#084.0#084.:3.0 7084.E.2047 :.0  $573 .9  -0. .205701.09 .3 /.8847 857317.9 9.0 &7.'17..07  3 . 3.80/'0#084.07 .5907%.:3 .:0.57084.07 57450793.07 /3  703/07 2 K3 9743 -7480723.  .2047 0- 807.

 .

85.

.

.:0 85. 57450793.208:11.

 .

0933706:089  85.3. 293. 706:089 3  3 .E.4 .3 3 .$573'   85.E.3/073907. 9 .3    ..09  4.: . : 3 - 85...: 3     49 3. ..3/07.05947 .E33 :95.. /3 .0794 :39:3.09 8 /.9.  4397407 9.9. 706:089 .07 $07..553 .OH:.07$07.0#084.-0.95939 H3-3.3 .42.79#084.07$07.07  6:9  .E. -..9...

E.07$07.3 3.0984/0.-. . ..O/: 97K  .943  5708843..E..E.96:..09  4/03/'0.73807..4.E. 85:800..3 39H:.E..3. -5..959743.  l  5O .7  '4 3g2  $:3 .E..9.  %:3H3 3.6:.09232 .3$! 89 5...45F5947..3$!973H3O:. 597K30-9.3 . %..9743:9.4E5/3 ..9.3 %:3H3 ... 43 .-7.97.49J33g36:.9.3:.0989H3.243.35E99730-947.3/..E..O299:8O9.4333. Og33 ..80  .E.35 25479&#$ 393/.4/3.  .E.  5E9 973 0- 97H3$! ..9.7 $%  .. 9 .O 3 32 3: 9743 ..4/0-:830884..'0  85.538..07!.3 .3/.397339.35E99730--3.O999.4 33 3. 97 . 83 7.97....08$9. .93..:3  %.497.:8942 9...25..3 38.-7.J / 3...8.-8. 5.  3 9743 29 8 9 9H: .39H:.79.3:.E.05708843974397.  9.4. 43...9.-8 .45F533.: 2..:... 94 7.07$07..7/%.943 % 8 5E9 973 ..-9793.3 5701  9 .4:807  $% $!$9.:3943/3 $% 93/98.:  5708843.0  %.39. -3$!.4 85.450  %.9H3.5293393...: %H39.3 995/38.:3. .$% %.E.38  O g3 .7%.E.3. 853.0$419.4'0 703/077.5J. 7H33O2.09  94  8 E..35E9973.  $ 9 5.9.-3H36:.'0.:6: .5.35 5E53. 3.:3..0...07$07.4.$07.: 35739  l: 3  O g3 9743 .  4397407 9..:8942 9.0 . .4'0#084.K807. 33 53 3 9H: . .5708843. .09.4/0%93 6:. 94 7...3$!   $%K $%-./.75909...4.  79 3: ..:3 3.3:.07 9K2'0998  85../329. . :9 7.3597K3 .$%  5708843. /: 97K 2 73 .!$07.. .3973 O.5708039. .E.$% .4/0  l: 9: 8O9 3 3.39.706:089  70854380 .7/%.4/0.74889028  9: . .3..O3 .94-0..5E99730-93:.42..339743%8/3 385.97.45F597::9.3 39H:.0.3.704:3/.7. .4/0.3 4/03/'0 .E.E.E.3.O299: 8O998...9.09 $07.3:.039-3 .:/0 $!..9432.     E.

4/0-4/ .: %4.9O.28&#.:34 O904.0 O. ...23 :3 34 O .9439743470 %H3.3706:0898.  .1 %3 43.:7 %4&# ..9439743472. 3.03 .597K3.93-E4..330.:53.0.E.-33. 37084:70-:3/0.30-.09708543808 :3. 39.4480    472.E.23 :3 .49E..3 %73.943 $%1472.&#8.450 E.1 147..:7 .3 3.943 3.$07. $" 86  %7::9$    !39J.3g38.4480 397433: 432 939. '356:F9995534 O .490780 E.470 .45034 O ..4:9 4:95:9.809 %4 9./:9    470.97.E. 3E972.9353..97H3.. ..45034 O ..2 E.4/09.5..4.993 129  l3/3. .: $03/4:95:99490.05943 :96:..23E97 .9.E.45F53.70/70.993 %H3.943...4..E.97.2547993:H3 #0/70...147%403 '356:F99. 129-:3/0 E.  472.89.9807.993.E..9743.7..943 3.059437.485790733 .7024.89.25479 2547929&#34 O .  3/339E3 939 5397g2 E.597K36:.9.397438.09 %4. 37084:7..-397438.2K3  .9 l:.3:333 E. 3:.397438.-E4 :39743.6:.O9 E.20880 G297439 .25479.147.E..4480 .E.E.4.993.E..  . 9...:77039857907 4:95:9 385790739 %.3&#2 .E. .9020391.0-:3/0.9O.4.9432.

.. $% .3:H39.3E5/3 . 99H3 %H39. 99H3 !2. 37084:70-:3/0.9.99  .2 .9994:39743533 ":...4-3 /38. 99H3.9J3 3      ":.3 .99 l93 /399 39.9:2-07 l3/38904. 99H39046:.9:..:3 1291472. :9 'J/ .9.6: 9.3:99743$%3...E.. 34 O 1291472.3:H39.90 l3/33904.42088..E.3 .7..129-:3/0 129809:3/0 E...9J3. E.0 %7::9.94.09743-:3/0   :H39. 34 O 1292088.$% -33H39K2 :333:H3 9.3 .33599 .-3 E.l 9 :9H3.4:9.E3.9H39:..995904 .24:39< ..:0 5.9 ....

147.97:3997.450/'..9:8     $.4.J/8.7.  02F9.:0 902< ...4/0.208< . %3 6:.97. .:0......9$%3.3..3/33 9393 .7593'.8 $.-08..2.147..-08 E..7 902 -03  03/   .4:9......:  .7.3$!.7 902 9028 3.7$9.9:8 89.293/3.4/0..3$!.

-7 .

E.49:....353:-3. 3936:.    E...9J3 3 E97..-.33    %0307.889.97436:E97K393 %7433: 97.38.3/07947. E97.29-3. 3 E97.O9934.9:..3/07 .E..3/43/943.5708843.147.. 9J3 3. 9...9J3 E97 O 8 .:73...4.3:.0        $%299..147.9J39743$%.E..7 .E.147.49.3 902 3.889..-E4E973:.:3 93..3$!8/39.E. .. 3..O9 . %743 43297H3 97.9:. !:75480. .-3 . 97E37.9:. 93936:.

E./3.059438 E.450 .-:9.809 .45.9.E.. 0.20907.8../3 97::9.!:75480 .0.. E97.4:95:9 97: :9.39.E.40307.229.0 ..90307.39. -:9943%09 .4:9 .K38..: %743.33...3 9.:  %7. :3.E.$:-29  .-397H3.J/97H3..598.O 96:3.E..39.9.35E9973$!-.9:.42947..... 9832.706:089 E97.:.:3.-3.90307.9J3..8.E. 5:75480 $%.J/ .7024.4:9 :9E97 93. 'J/.. .7.5:754803.

3.997H3.  $%.E97 .1 .39.35 97.:3.J/95.4.3996:9.59.03 .59H29.147%403 'J/.E.$.$%.../335.4480 .35.3 :.30-.399.45F53.35  .:8:-29   %43/943. .490780 47.39..8.147.4. ..3.39.:3.E.443/943.2.4.: l:9H3.:3.

O96:8. %74397..39.39.4.E.E973 3 .:9 93-E43.8.:  .353./335.:  93.

:    .39.O93-E48. 3/3.. 35:8.

Master your semester with Scribd & The New York Times

Special offer for students: Only $4.99/month.

Master your semester with Scribd & The New York Times

Cancel anytime.