Hôm nay chúng ta tiếp tục phần bài JSF . Chúng ta sẻ hiện thực các phạm vi trong managed beans. Và các hoạt động của các đổi tượng Request và Response, và annotation @ManagredProperty (dependency injection) in JSF
Source code : Managed Bean
Managed Bean
- Chúng ta có thể tùy chỉnh name khi tạo bean .
Ví dụ : @ManagedBean( name = “yourBeanName” ) => #{ yourBeanName.attributes }.
- Điều khiển Scope Bean ( Phạm vi của một Bean ).
Từ ban đầu chúng ta sử dụng Scope mặc định là [ Request ].
Chúng ta có các scope sau đây : request, session, application, view, none, custom
Chúng ta có thể thiết lập scope cho bean của chúng ta trong file faces-config.xml or sử dụng annotations [ example @SessionScoped ]. trên bean khi chúng ta tạo ra.
- @RequestScoped : Mặc định của mổi Bean, Nó tạo ra một new instance cho mổi lần HTTP request. Kể từ khi Bean của chúng ta được sử dụng để show các data lên các input form khi load page lên. Điều này có nghĩ là chúng ta khởi tạo Bean 2 lần [ lần thứ nhất khi form hiển thị, và lần 2 khi form được submit].
- @SessionScoped : Thiết lập Session scope cho Bean. Nếu trên cùng một user với cùng một cookie (JSESSIONID) trả về trước khi session timeout. Thì chúng ta sẻ sử dụng Bean mà chúng ta khởi tạo. Khi thiết lập Session Scope cho Bean bạn nên thiết lập Serializable cho Bean.
- @ApplicationScopded : Thiết lập Application Scope cho Bean. Khi chúng ta muốn Share Bean cho all User sử dụng. Phải nên cẩn thận khi dùng phạm vi này, có thể một User nào đó thay đổi Bean vì vậy không nên thay đổi Bean khi dùng phạm vi này, và nên thiết lập synchronize access cho Bean.
- @ViewScoped : Trên cùng một Bean – cùng một User – Cùng một page (example : Event handlers hoặc sử dụng Ajax ) bean của chúng ta nên thiết lập Serializable
- @CustomScoped (value=”#{someMap}”) : Bean này được dùng để lưu trữ trong một Map. và chúng ta có thể điều lifecycle cho riêng chúng ta .
- @NoneScoped : Khởi tạo một bean và Bean này không có Scope. hữu ích khi chúng ta tham chiếu đến Bean này bởi một Bean khác.
- Các dùng thường dùng sau Anonation @ManagedBean.
Vd: @ManagedBean
@SessionScoped
Public class ClassBean {……..}
1 – Application Scope
Khi nào chúng ta nên dùng Scope này.
- Thiết lập Bean với trạng thái không bao giờ thay đổi.
- Thường chỉ thiết lập cho navigation rule ( No setter / getter)
- Ví dụng chúng ta có thể thiết lập 1 List các item cho việc lựa chọn tring Drop Down Menus
- VD <h:selectOnemenu value=”#{requestScopeBean.choice}”>
- <f:selectItems value=”#{applicationScopeBean.options}”/>
- </h:selectOneMenu>
- Sử dụng để thiết lập một Data Structures như một properties trong main beans : @ManagedBeanProperty
- Share Bean thông qua all Users vs all pages, You củng nên cẩn thận sử dụng synchronization để né tránh race conditions.
1.1 – Syntax
Cách 1 :
@ManagedBean @ApplicationScoped public class ApplicationBean {}
ApplicationBean khi chúng ta thể hiện lần đầu tiên ( Sử dụng nó ). All user và All request share trên Bean này sẻ củng 1 instance.
Cách 2 :
@ManagedBean(eager=true) @ApplicationScoped public class ApplicationBeanBigData {}
ApplicationBeanBigData được thể hiện khi ứng dụng được load ( thường khi server starts ). Sau lần thể hiện đó all users vs all request sẻ hiện thực trên cùng thể hiện. Nó hữu ích khi Bean của chúng ta có 1 cấu trúc dữ liệu lớn ( big data) và mất khá nhiều thời gian để khởi tạo nó.
1.2 – Không thiết lập Các trạng thái thay đổi khi dùng Application Scope
- Không thể hiển của variable, chỉ có các action controller method.
- Application scope ngăn chặn nhựng đối tượng không cần thiết khi intantiation.
- Khi thể hiện các small objects thì rất nhanh vì vậy việc để tối ưu hóa (optimization) có lẻ khổng thể được đo lường. Nó có thể gậy ra lỗi lầm khi chúng ta thêm input field và nó truy cập vào các getter/setter . Vì vậy nó thường được dùng để chuyển hướng trang
- Được hiện thực khi có một lượng data lớn cần load. ( Đặc biệt các Map có chứa nhiều data ) và nó hoạt động rất tốt. ( Ví dụ khi chúng ta có 1 lượng lớn các List Object cho các đối tượng như drop down menus or Maps để hiện thực business logic như ví dụ lần trước ta dùng )
1.3 – Example cơ bản như sau :
@ManagedBean @ApplicationScoped public class ApplicationBean { // no variable (not attribute) // set action controller for bean public String actionController(){ return "your-page"; }
2 – Session Scope
- Mục đích Bean thể hiện được tái sử dụng nếu [ Cùng trên một User ] – [ Cùng trên một Browser session ]
- Thường xuyên dự trên cookies, có thể dự trên URL để tái sử dụng bean.
- Hữu ích khi sử dụng :
-
Ghi nhớ user preferences.
-
Thiết lập lại các values từ các entries trước
-
Tính toán List các data của người dùng ( Shopping carts )
- Bean thường Seriablizable. Một vài servers thường lưu session data trên disk khi restart, và các web apps cần để thiết lập lại session cho lần dùng kế tiếp.
Request vs Response Object.
Tại sao chúng ta cần 2 đối tượng này. Khi chúng ta có thể truy xuất data thông qua Bean một cach rất dể dàng như các bài trước ta thầy. Nhưng các Bean không thể làm các điều sau đây các bạn xem qua khi 2 đối tượng Request vs Response in JSF
- Request Object
– HIện thực các thao tác trên session một cách rõ ràng.( Thay đổi các giá trị của session, session timeout, remove session..)
– Thao tác trên các cookies một cách rõ ràng ( VD : long-lived cookies).
– Đọc các request headers (vd : User-Agent, ..)
– Tra cứu các request host name.
- Response Object
– Thiết lập status codes, respnse headers, long-lived cookies…
- Giải pháp ( Solution ) kHá tương tự như Struts chung ta dùng các static method để gọi 2 đứa nó.
ExternalContext context = FacesContext.getCurrentInstance().getExternalContext();
HttpServletRequest request = (HttpServletRequest) context.getRequest();
HttpServletResponse response = (HttpServletResponse) context.getResponse();Note : Trong các môi trường khác nhau bạn phải cast getRequest, getResponse vè các đối tượng mà chúng ta cần, VD trong môi trường portlet chúng ta cast 2 đối tượng là PortletRequest vs PortletResponse.
Sử dụng @ManagedProperty ( Dependency injection )
JSF hổ trợ cơ bản cho việc sử dụng (Dependency injection), bạn có thể thiết lập values đến managed bean property mà không cần hardcoding nó vào trong class Bean.
Chắc hẵn nó thì không có năng lực so với Spring . nhưng vẫn hữu ích cho việc sử dụng trong JSF.
Cách 1 :
@ManagedProperty (value=”#{yourBean}”)
private YoutType someType;
Note : Setter method phải được thiết lập cho property này. trong ví dụ trên chúng ta phải có setSomeType(YourType type); Bạn có thể sử dụng thuộc tính name của @ManagedProperty nếu setter method thì không match với field name.
Cách 2 :
Bạn có thể hiện thực bean tại thời điểm load app
@ManagedBean(eager=true) @ApplicationScoped public class ApplicationBeanBigData {}
Điều này hữu ích khi bean của chúng ta được inject vào trong main bean. và Bean được inject thì thường được share
như môt service. Chúng ta thường dùng main bean chửa data khi load.
Note : faces-config tốt hơn annotations và Spring cách lựa chọn tốt nhất và bạn có thể dùng Spring trực tiếp trong
JSF application
Example cho ví dụ này chúng ta sẻ thay đổi Example login của chúng ta từ ví dụ trước như sau :
Thay đổi tại class LoginBean.java
@ManagedProperty(value="#{loginUtils}") private LoginUtils loginUtils; public void setLoginUtils(LoginUtils loginUtils) { this.loginUtils = loginUtils; }
Thay đổi class LoginUtils.java như sau :
@ManagedBean(eager=true) @ApplicationScoped public class LoginUtils {..... }
Kết quả run tương tự, chúc các bạn thành công .