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

2. Spring MVC

Mục tiêu

Luyện tập sử dụng Spring controller

Mô tả

Chuyển đổi một app web backend có sẵn, được viết bằng Java servlet thành sử dụng Spring MVC

Hướng dẫn

Bước 1: tiếp nhận dự án

Tải app trong file đính kèm, thăm dò mã, thực hiện các cài đặt cần thiết để khởi chạy dự án, và dùng thử các tính năng hiện tại.

Bước 2: giấu các tệp jsp khỏi Tomcat

Hiện tại các file jsp vẫn được Tomcat tự động compile thành các servlet và hệ quả là vẫn có thể truy cập được. Điều này có thể gây ra rủi ro rò rỉ thông tin. Cách để hạn chế điều này là đưa các template jsp ra khỏi thư mục webapp, hoặc đưa vào trong thư mục WEB-INF. Hãy lựa chọn cách thứ 2, đưa thư mục webapp/customers vào trong thư mục webapp/WEB-INF/templates/.

Sửa đường dẫn tương ứng tại controller:

ModelAndView modelAndView = new ModelAndView("WEB-INF/templates/customers/list.jsp");

Bước 3: ủy quyền cho view resolver phân giải view

Hiện tại controller đang phải tự biết vị trí chính xác của temlate, để có thể tùy biến vị trí của template tốt hơn mà không phải compile lại app, hãy cấu hình để ủy quyền phân giải view cho view resolve. Bổ sung bean như sau trong app-conf.xml:

<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/templates/"/>
<property name="suffix" value=".jsp"/>
</bean>

Nhờ có cấu hình về prefix và subfix, controller giờ chỉ cần quan tâm cụ thể vào tên view:

ModelAndView modelAndView = new ModelAndView("customers/list");

Bước 4: sử dụng Spring controller để xử lý request xem thông tin chi khách hàng

1. Bổ sung handle method cho controller:

@GetMapping("/customers/{id}")
public ModelAndView showInformation(@PathVariable Long id) {
ModelAndView modelAndView = new ModelAndView("customers/info");
Customer customer = customerService.findOne(id);
modelAndView.addObject("customer", customer);
return modelAndView;
}

2. Sửa đường dẫn tại màn hình list:

<a href="/customers/${c.id}">${c.name}</a>

3. Thay thế mã jsp snipet tại màn hình info bằng mã jstl expression. Hãy chắc chắn thông tin hiển thị đúng trước khi sang bước tiếp theo.
4. Có thể kết hợp sử dụng @GetMapping và @RequestMapping để dễ thể hiện ý đồ hơn:

@Controller
@RequestMapping("customers")
public class CustomerController {
@Autowired
private CustomerService customerService;

@GetMapping
public ModelAndView showList() {
//...
}

@GetMapping("{id}")
public ModelAndView showInformation(@PathVariable Long id) {
//...
}
}

Bước 5: sử dụng Spring controller để xử lý request yêu cầu cập nhật thông tin khách hàng

1. Tạo handle method để xử lý post request từ màn hình info. Sau post request luôn theo sau là một response redirect.

@PostMapping
public String updateCustomer(
@RequestParam Long id,
@RequestParam String name,
@RequestParam String email,
@RequestParam String address
) {
return "redirect:/customers";
}

2. Thêm mã để cập nhật customer:

Customer customer = new Customer(id, name, email, address);
customerService.save(customer);
return "redirect:/customers";

3. Mặc định, với các request param tương ứng với dữ liệu nguyên thủy thì có thể bỏ annotation đi:

public String updateCustomer(Long id, String name, String email, String address) {

4. Thậm chí, bởi tên của các param đang khớp với tên các thuộc tính của Customer, có thể sử dụng cơ chế mass assignment để rút gọn:

@PostMapping
public String updateCustomer(Customer customer) {
customerService.save(customer);
return "redirect:/customers";
}

Bước 6: chuyển đổi cấu hình xml thành cấu hình Java

1. Tạo một config adapter với annatation @Configuration để thay thế cho app-conf.xml:

@Configuration
@EnableWebMvc
@ComponentScan("cg.wbd.grandemonstration")
public class AppConfig extends WebMvcConfigurerAdapter {
@Bean
public ViewResolver viewResolver() {
InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
viewResolver.setPrefix("/WEB-INF/templates/");
viewResolver.setSuffix(".jsp");
return viewResolver;
}

@Bean
public CustomerService customerService() {
return new SimpleCustomerServiceImpl();
}
}

2. Tạo một dispatcher initializer để thay thế cho web.xml:

public class AppInit extends AbstractAnnotationConfigDispatcherServletInitializer {
@Override
protected Class<?>[] getRootConfigClasses() {
return new Class[]{AppConfig.class};
}

@Override
protected Class<?>[] getServletConfigClasses() {
return new Class[0];
}

@Override
protected String[] getServletMappings() {
return new String[]{"/"};
}
}
cms.zip cms.zip 

Leave a Reply

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