「Spring Boot #10」@RequestMapping+@PostMapping+@ModelAttribute+@RequestParam+Web To-Do Thymeleaf

Giới thiệu

Trong bài hôm nay chúng ta sẽ tìm hiểu cách handle request POST của Spring Boot.

Trước đó, bạn nên biết

  1. 「Spring Boot #8」Tạo Web Helloworld với @Controller
  2. 「Spring Boot #9」Giải thích cách Thymeleaf vận hành + Expression + Demo Full

@PostMapping

@PostMapping có nhiệm vụ đánh dấu hàm xử lý POST request trong Controller.

Khái niệm về GETPOST hi vọng các bạn đã biết rồi và tôi sẽ không đề cập thêm trong bài này. Còn nếu chưa biết bạn có thể tham khảo tại wiki: Hypertext Transfer Protocol

Ví dụ:

Tôi có 2 hàm xử lý, một cho GET method và một cho POST.

Cả hai đều chung đường dẫn nhưng bạn nên biết rằng cùng một path nhưng khác method thì sẽ xử lý khác nhau.

@Controller
public class WebController {
    @GetMapping("/addTodo")
    public String addTodo(Model model) {
        return "addTodo";
    }

    @PostMapping("/addTodo")
    public String addTodo(Model model) {
        return "success";
    }
}

Từ đây bạn có thể suy ra cách handle cho các method khác như PUT, DELETE, v.v..

  1. @PutMapping
  2. @DeleteMapping

@RequestMapping

Trong trường hợp bạn muốn tất cả các method đều dùng chung một cách xử lý thì có thể sử dụng Annotation @RequestMapping.

@RequestMapping là một annotation có ý nghĩa và mục đích sử dụng rộng hơn các loại @GetMapping, @PostMapping,v.v..

ví dụ:


@Controller
@RequestMapping("api/v1")
public class WebController {

    // Đường dẫn lúc này là: /api/v1/addTodo và method GET
    @RequestMapping(value = "/addTodo", method = RequestMethod.GET)
    public String addTodo(Model model) {
        return "addTodo";
    }

    // Đường dẫn lúc này là: /api/v1/addTodo và method POST
    @RequestMapping(value = "/addTodo", method = RequestMethod.POST)
    public String addTodo(@ModelAttribute Todo todo) {
        return "success";
    }
}

Nếu không chỉ định method cho @RequestMapping thì nó sẽ nhận toàn bộ các method.

Website To-do

Vẫn còn một vài kiến thức tôi cần giới thiệu với các bạn.

Tuy nhiên tôi sẽ sử dụng ví dụ để giúp bạn hiểu nó nhanh hơn.

Chúng ta sẽ làm một WebApp quản lý công việc và từ đó tìm hiểu cách gửi dữ liệu lên Server thông qua 2 method GETPOST.

Cài đặt

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <packaging>pom</packaging>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.0.5.RELEASE</version>
        <relativePath /> <!-- lookup parent from repository -->
    </parent>
    <groupId>me.loda.spring</groupId>
    <artifactId>spring-boot-learning</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>spring-boot-learning</name>
    <description>Everything about Spring Boot</description>

    <properties>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>

        <!--spring mvc, rest-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <!-- thymeleaf -->
        <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>
    </dependencies>

    <build>
        <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
        </plugin>
        </plugins>
    </build>

</project>

Cấu trúc thư mục:

alt text

Tạo model

Chúng ta sẽ tạo ra một đối tượng gọi là Todo để thể hiện thông tin.

Trong bài viết sử dụng Lombok

Todo.java

import lombok.Data;

@Data
public class Todo {
    public String title;
    public String detail;
}

GET /listTodo - Lấy danh sách các việc cần làm

Chúng ta sẽ dùng đường dẫn /listTodo để lấy ra danh sách việc cần làm.

Thiết kế method cho đường dẫn /listTodoGET.

WebController.java

@Controller
public class WebController {
    // Sử dụng tạm List để chứa danh sách công việc
    // Thay cho Database.
    // Chỉ dùng cách này khi DEMO ^^
    List<Todo> todoList = new CopyOnWriteArrayList<>();

    /*
        @RequestParam dùng để đánh dấu một biến là request param trong request gửi lên server.
        Nó sẽ gán dữ liệu của param-name tương ứng vào biến
     */
    @GetMapping("/listTodo")
    public String index(Model model, @RequestParam(value = "limit", required = false) Integer limit) {
        // Trả về đối tượng todoList.
        // Nếu người dùng gửi lên param limit thì trả về sublist của todoList
        model.addAttribute("todoList", limit != null ? todoList.subList(0, limit) : todoList);

        // Trả về template "listTodo.html"
        return "listTodo";
    }
}

Khi tôi request lên server như này http://localhost:8080/listTodo?limit=2.

Thì cái đoạn ?limit=2Request Param.

Spring Boot sẽ tự xử lý và gán số 2 vào biến Integer limit hộ chúng ta.

Nếu chúng ta không gửi gì lên, thì limit sẽ là null.

listTodo.html

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
  <head>
    <meta charset="UTF-8" />
    <title>Loda To-do</title>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />

    <!--css-->
    <link th:href="@{/css/bootstrap.css}" rel="stylesheet" />
    <link th:href="@{/css/main.css}" rel="stylesheet" />

    <!--js-->
    <script th:src="@{/js/bootstrap.js}"></script>
  </head>
  <body>
    <h1>Danh sách việc cần làm:</h1>

    <ul>
      <!--Duyệt qua toàn bộ phần tử trong biến "todoList"-->
      <li th:each="todo : ${todoList}">
        <!--Với mỗi phần tử, lấy ra title và detail-->
        <span th:text="*{todo.getTitle()}"></span> : <span th:text="*{todo.getDetail()}"></span>
      </li>
    </ul>

    <a th:href="@{/addTodo}" class="btn btn-success"> + Thêm công việc</a>
  </body>
</html>

GET /addTodo - Trang thêm công việc

GET /addTodo sẽ trả về webpage cho ngừoi dùng nhập thông tin công việc và thêm vào danh sách việc cần làm.

WebController.java

@GetMapping("/addTodo")
public String addTodo(Model model) {
    // Thêm mới một đối tượng Todo vào model
    model.addAttribute("todo", new Todo());
    // Trả về template addTodo.html
    return "addTodo";
}

addTodo.html

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
  <meta charset="UTF-8" />
  <title>Loda To-do</title>
  <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />

  <!--css-->
  <link th:href="@{/css/bootstrap.css}" rel="stylesheet" />
  <link th:href="@{/css/main.css}" rel="stylesheet" />

  <!--js-->
  <script th:src="@{/js/bootstrap.js}"></script>

</head>
<body>
<h1>To-do</h1>

<form th:action="@{/addTodo}" th:object="${todo}" method="post">
  <p>title: <input type="text" th:field="*{title}" /></p>
  <p>detail: <input type="text" th:field="*{detail}" /></p>
  <p><button type="submit" class="btn btn-success">Add</button></p>
</form>
</body>

</html>

<form></form> là thẻ tag mà bạn cần biết khi làm Web. Nó tạo Request Form gửi tới server với thông tin và các thẻ <input> trong nó.

Ở đây, tôi gán vào Model một đối tượng Todo.

Trong form, chúng ta lấy ra đối tượng Todo và chỉ định bởi th:object="${todo}"

Gán thông tin người dùng nhập vào Todo bằng cú pháp th:field=*{tên_thuộc_tính}.

Bấm Button thì form sẽ gửi request POST có chứa Todo lên địa chỉ /addTodo.

POST /addTodo - Thêm công việc vào list

WebController.java

    /*
    @ModelAttribute đánh dấu đối tượng Todo được gửi lên bởi Form Request
     */
@PostMapping("/addTodo")
public String addTodo(@ModelAttribute Todo todo) {
    // Thêm đối tượng todo vào list
    todoList.add(todo);
    // Trả về trang thành công success.html
    return "success";
}

success.html

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
  <meta charset="UTF-8" />
  <title>Loda To-do</title>
  <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />

  <link th:href="@{/css/bootstrap.css}" rel="stylesheet" />
  <link th:href="@{/css/main.css}" rel="stylesheet" />

</head>
<body>
<h1>To-do</h1>
<h1>Thêm thành công!</h1>

<a th:href="@{/listTodo}" class="btn btn-primary">Xem danh sách công việc</a>

</body>

</html>

Chạy chương trình.

Sau khi hoàn thiện xong các phần trên, chúng ta sẽ bổ sung index.htmlApp.java để khởi động server Web

App.java

@SpringBootApplication
public class App {
    public static void main(String[] args) {
        SpringApplication.run(App.class, args);
    }
}

index.html

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
  <meta charset="UTF-8" />
  <title>Loda To-do</title>
  <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />

  <!--css-->
  <link th:href="@{/css/bootstrap.css}" rel="stylesheet" />
  <link th:href="@{/css/main.css}" rel="stylesheet" />

  <!--js-->
  <script th:src="@{/js/bootstrap.js}"></script>
</head>
<body>
<h1>Todo App</h1>

<a th:href="@{/listTodo}" class="btn btn-primary">Xem danh sách</a>
<a th:href="@{/addTodo}" class="btn btn-success">+ Thêm công việc</a>
</body>

</html>

Khởi động ứng dụng vào truy cập vào địa chỉ: http://localhost:8080/

alt text

Nhấn vào nút Xem Danh Sách để đi tới GET /listTodo

alt text

Bấm Thêm Công Việc để đi tới trang GET /addTodo

alt text

Nhập thông tin và bấm Add để gửi thông tin tới server POST /addTodo.

Nếu thành công, server sẽ trả về thành công.

alt text

Xem lại danh sách công việc bằng cách bấm vào Xem danh sách công việc.

alt text

Nếu danh sách quá nhiều, chúng ta có giới hạn bằng cách truyền lên param limit.

Ví dụ tôi truyền vào là http://localhost:8080/listTodo?limit=2

alt text

Kết quả chỉ còn 2 việc phải làm =)))

Kết

Đây là một bài viết trong Series làm chủ Spring Boot, từ zero to hero

Như mọi khi, toàn bộ code tham khảo tại Github


Bình luận


White
{{ comment.user.name }}
Bỏ hay Hay
{{comment.like_count}}
Male avatar
{{ comment_error }}
Hủy
   

Hiển thị thử

Chỉnh sửa

White

https://loda.me

48 bài viết.
14 người follow
Kipalog
{{userFollowed ? 'Following' : 'Follow'}}
Cùng một tác giả
White
5 0
Vì sao bạn nên học Java? Trước khi nói Spring Boot, chúng ta nói về nền tảng của nó, chính là Java. Java ra đời năm 1991, tới nay thì đã gần 30 n...
https://loda.me viết 3 tháng trước
5 0
White
5 0
Vì sao bạn nên học Java? Trước khi nói Spring Boot, chúng ta nói về nền tảng của nó, chính là Java. Java ra đời năm 1991, tới nay thì đã gần 30 n...
https://loda.me viết 3 tháng trước
5 0
White
3 0
Xin chào tất cả các bạn, trước khi đi vào chi tiết bài hôm nay, các bạn cần đọc cho mình các khái niệm sau: 1. Khái niệm tightcoupling (liên k...
https://loda.me viết 3 tháng trước
3 0
Bài viết liên quan
White
0 0
Trong bài viết này, một số hình ảnh hoặc nọi dung có thể bị thiếu do quá trình chế bản. Vui lòng xem nội dung ở blog gốc sau: (Link) (Link), chúng...
programmerit viết gần 4 năm trước
0 0
White
2 0
I used Spring boot, Hibernate few times back then at University, I'v started using it again recently. In this (Link), I want to check how Spring J...
Rey viết 7 tháng trước
2 0
{{like_count}}

kipalog

{{ comment_count }}

bình luận

{{liked ? "Đã kipalog" : "Kipalog"}}


White
{{userFollowed ? 'Following' : 'Follow'}}
48 bài viết.
14 người follow

 Đầu mục bài viết

Vẫn còn nữa! x

Kipalog vẫn còn rất nhiều bài viết hay và chủ đề thú vị chờ bạn khám phá!