[Thực hành] Ứng dụng quản lý danh sách khách hàng

1. Tổng quan

Mục tiêu

Luyện tập phát triển phần mềm web backend, sử dụng Spring MVC.

Hướng dẫn

Bước 1: tiếp nhận một dự án web backend sử dụng Java Servlet

Tải file nén đính kèm, giải nén, mở dự án, làm các bước cài đặt cần thiết, build dự án và mở bằng Tomcat.

Thăm dò mã có sẵn trong dự án và tìm dùng thử các chức năng của dự án như hiện danh sách khách hàng, hiện thông tin một khách hàng, cập nhật thông tin khách hàng.

Bước 2: khởi động Spring MVC Dispatcher Servlet

1. Tại file build.gradle bổ sung thư viện spring-webmvc:

dependencies {
  compile group: 'javax.servlet', name: 'servlet-api', version: '2.5'
  compile group: 'org.springframework', name: 'spring-webmvc', version: '4.3.24.RELEASE'
}

2. Điều hướng toàn bộ request tới dispatcher servlet, bằng cách xóa tất cả các khai báo servlet hiện có và thay thế bằng Spring MVC DispatcherServlet:

<?xml version="1.0" encoding="UTF-8"?>
<web-app...>
<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>

3. Dispatcher servlet cần được cung cấp một cấu hình app context để có thể khởi động vòng đời của nó. Một cách để có cấu hình này là tạo file cấu hình xml, chẳng hạn WEB-INF/app-conf.xml:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
</beans>

4. Khai báo bổ sung file cấu hình này cho dispatcher. Ta cũng có thể cấu hình để dispatcher ngay lập tức bắt đầu vòng đời của nó ngay khi app được khởi động, mà không cần chờ tới request đầu tiên:

<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>WEB-INF/app-conf.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>

Sau bước này hãy khởi động lại app, để ý xem dòng log “‘dispatcher’: initialization completed in *** ms” có xuất hiện hay không.

Bước 3: sử dụng Spring MVC controller để xử lý request xem danh sách khách hàng

1. Tạo một class controller (được ấn định bằng annotation @Controller), bổ sung cho nó một handle method có khả năng thông báo ra tên của view cần dùng.

@Controller
public class CustomerController {
@GetMapping("/customers")
public String showList() {
return "customers/list.jsp";
}
}

2. Cấu hình vào file app-conf.xml để Spring MVC quét danh sách các controller khả dụng theo annatation và theo package:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd">
<context:component-scan base-package="cg.wbd.grandemonstration"/>
<mvc:annotation-driven/>
</beans>

3. Bật thử app và xác nhận rằng controller đã hoạt động hay chưa bằng cách gửi request tới “:8080/customers”. 

4. Sửa thẻ anchor tại màn hình info theo đường dẫn mới:

<a href="/customers">Back to list</a>.

Bước 4: tách riêng model và view

1. Hiện tại các template jsp đang tự xử lý data của mình, hãy di chuyển những mã đó vào controller:

@Controller
public class CustomerController {
private CustomerService customerService = CustomerServiceFactory.getInstance();

@GetMapping("/customers")
public String showList(HttpServletRequest request) {
List<Customer> customers = customerService.findAll();
request.setAttribute("customers", customers);
return "customers/list.jsp";
}
}

2. Thay thế những mã tự xử lý data hiện tại bằng mã truy cập data từ model:

<%
List<Customer> customers = (List<Customer>) request.getAttribute("customers");
%>
...
There are <%= customers.size() %> customer(s) in list.

Để mã được gọn hơn nữa, hãy sử dụng thư viện jstl, bổ sung thư viện vào file build.gradle

compile group: 'javax.servlet', name: 'jstl', version: '1.2'

Và thay thế các jsp snipets hiện tại bằng jstl expression:

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
...
There are ${requestScope.customers.size()} customer(s) in list.
...
<c:forEach var="c" items="${requestScope.customers}">
<tr>
<td>
<c:out value="${c.id}"/>
</td>
<td>
<a href="info.jsp?id=${c.id}">${c.name}</a>
</td>
<td>
<c:out value="${c.email}"/>
</td>
<td>
<c:out value="${c.address}"/>
</td>
</tr>
</c:forEach>

3. Sử dụng api Model thay vì HttpServletRequest

Spring MVC có cơ chế riêng để khai báo model cho template:

@GetMapping("/customers")
public String showList(Model model) {
List<Customer> customers = customerService.findAll();
model.addAttribute("customers", customers);
return "customers/list.jsp";
}

4. Sử dụng vỏ bọc dependence injection để gỡ phụ thuộc vào lớp implement

Khai báo một service bean vào file app-conf.xml:

<?xml version="1.0" encoding="UTF-8"?>
<beans ...>
// other configs...
<bean name="customerService" class="cg.wbd.grandemonstration.service.impl.SimpleCustomerServiceImpl"/>
</beans>

Sử dụng annotation @Autowire để chỉ định “tiêm” bean cần thiết vào cho controller:

@Controller
public class CustomerController {
@Autowired
private CustomerService customerService;
// ...
}

5. Sử dụng api ModelAndView 

Thay vì để controlle trả về thông tin view qua kết quả return String, và trả về model qua tham chiếu Model, có thể sử dụng api ModelAndView để mã dễ đọc hơn. Đây là cách làm được khuyến khích.

@GetMapping("/customers")
public ModelAndView showList() {
ModelAndView modelAndView = new ModelAndView("customers/list.jsp");
List<Customer> customers = customerService.findAll();
modelAndView.addObject("customers", customers);
return modelAndView;
}

Tổng kết

Bạn đã bước đầu biết cách sử dụng dispatcher servlet, bài sau sẽ tiếp tục sử dụng những khả năng mà Spring MVC mang lại để hoàn toàn chuyển đổi dự án này thành sử dụng Spring MVC.

cms.zip cms.zip 

Leave a Reply

Your email address will not be published. Required fields are marked *