Spring Boot, Vue.js, Axios 및 Thymeleaf with Bootstrap 4개 커밋

심호흡을 하고, 참아...

4개의 짧고 쉬운 커밋에서 Thymeleaf(Bootstrap 포함)를 통해 서버 측 렌더링 페이지를 제공하는 Spring Boot 앱과 Axios를 사용하여 서버에 비동기식 요청을 만들어 페이지를 다시 로드하지 않고 데이터로 페이지를 업데이트하는 Vue.js 스크립트를 얻을 수 있습니다. 다시 서버에서 전체 페이지.

... 풀어 주다! 이전 문구를 설명하는 것이 구현하는 것보다 오래 걸릴 수 있습니다. 그러니 해봅시다.

커밋 #1 - Spring Initializr



이것은 쉽습니다. 첫 번째 커밋은 Spring Initializr + 몇 가지 추가 항목의 기본 Spring Boot 애플리케이션입니다.

자체 버전 다운로드from this link를 생성할 수 있습니다(일부 종속 항목으로 이미 채워져 있음).

원하는 IDE에서 프로젝트를 로드한 후 pom.xml 파일에 다음을 추가합니다.

<dependency>
    <groupId>org.webjars</groupId>
    <artifactId>bootstrap</artifactId>
    <version>4.4.1</version>
</dependency>
<dependency>
    <groupId>org.webjars</groupId>
    <artifactId>webjars-locator</artifactId>
    <version>0.38</version>
</dependency>

커밋 #2 - 기본 앱



이 커밋은 길 수 있지만 전혀 복잡하지 않습니다. 역할 및 사용자 엔터티를 추가합니다.

@Entity(name = "role")
@Data
public class Role {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private long id;

    private String name;
}

@Entity(name = "user")
@Data
public class User {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private long id;

    private String firstName;
    private String lastName;

    @ManyToOne
    @JoinColumn(name = "role_id")
    private Role role;
}

그리고 해당 Spring Data JPA 리포지토리:

@Repository
public interface RoleRepository extends JpaRepository<Role, Long> {
}

@Repository
public interface UserRepository extends JpaRepository<User, Long> {
}

Thymeleaf를 통해 서버 측 렌더링 페이지를 제공하는 컨트롤러를 추가합니다.

@Controller
public class MainController {

    @RequestMapping("/")
    public String index() {
        return "index";
    }
}

그리고 index.html 폴더에 있는 resources/templates 페이지 자체:

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <link href='/webjars/bootstrap/css/bootstrap.min.css' rel='stylesheet'>

    <meta charset="UTF-8">
    <title>Home</title>
</head>
<body>

<div th:replace="fragments/header :: header"></div>

<script src="/webjars/jquery/jquery.min.js"></script>
<script src="/webjars/bootstrap/js/bootstrap.min.js"></script>
</body>
</html>
<div th:replace...를 확인하셨습니까? 이것은 코드를 재사용할 수 있는 Thymeleaf의 깔끔한 기능입니다. 다음은 header.html 폴더의 재사용 가능resources/templates/fragments입니다.

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <link href='/webjars/bootstrap/css/bootstrap.min.css' rel='stylesheet'>

    <meta charset="UTF-8">
    <title>Restaurants</title>
</head>
<body>

<nav class="navbar navbar-expand-lg navbar-dark bg-dark" th:fragment="header">
    <a class="navbar-brand" href="/">Home</a>
    <button aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation"
            class="navbar-toggler" data-target="#navbarSupportedContent" data-toggle="collapse" type="button">
        <span class="navbar-toggler-icon"></span>
    </button>

    <div class="collapse navbar-collapse" id="navbarSupportedContent">
        <ul class="navbar-nav mr-auto">
            <li class="nav-item dropdown">
                <a aria-expanded="false" aria-haspopup="true" class="nav-link dropdown-toggle" data-toggle="dropdown"
                   href="#" id="navbarDropdown" role="button">
                    Entities
                </a>
                <div aria-labelledby="navbarDropdown" class="dropdown-menu">
                    <a class="dropdown-item" href="/users">Users</a>
                    <a class="dropdown-item" href="/roles">Roles</a>
                    <div class="dropdown-divider"></div>
                    <div class="dropdown-item-text p-4 text-muted" style="max-width: 200px;">
                        <p>
                            Administrative pages to list, edit, create and remove entities.
                        </p>
                    </div>
                </div>
            </li>
        </ul>
        <form class="form-inline my-2 my-lg-0">
            <input aria-label="Search" class="form-control mr-sm-2" placeholder="Search" type="search">
            <button class="btn btn-outline-success my-2 my-sm-0" type="submit">Search</button>
        </form>
    </div>
</nav>

<script src="/webjars/jquery/jquery.min.js"></script>
<script src="/webjars/bootstrap/js/bootstrap.min.js"></script>
</body>
</html>

커밋 #3 - 엔터티용 HTML 템플릿



서버측 렌더링 템플릿 및 컨트롤러를 추가합니다. 템플릿은 역할 및 사용자를 위한 기본 html 페이지를 제공합니다.

이것이 새로운 것입니다RoleController.

@Controller
public class RoleController {

    @GetMapping("/roles")
    public String rolesPage() {
        return "roles";
    }
}

그리고 UserController:

@Controller
public class UserController {

    @GetMapping("/users")
    public String users() {
        return "users";
    }
}
roles.html 페이지의 HTML:

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <link href='/webjars/bootstrap/css/bootstrap.min.css' rel='stylesheet'>

    <meta charset="UTF-8">
    <title>Roles</title>
</head>
<body>

<div th:replace="fragments/header :: header"></div>

<br><br>

<div class="container" id="main">

    <table class="table table-striped table-bordered">
        <thead>
        <tr>
            <th>Role ID</th>
            <th>Role Name</th>
            <th>Actions</th>
        </tr>
        </thead>
        <tbody>
        <tr>
            <td></td>
            <td></td>
            <td>
                <a>Edit</a>
                <a>Delete</a>
            </td>
        </tr>
        </tbody>
    </table>
</div>

<script src="/webjars/jquery/jquery.min.js"></script>
<script src="/webjars/bootstrap/js/bootstrap.min.js"></script>
</body>
</html>

users.html 페이지:

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <link href='/webjars/bootstrap/css/bootstrap.min.css' rel='stylesheet'>

    <meta charset="UTF-8">
    <title>Users</title>
</head>
<body>

<div th:replace="fragments/header :: header"></div>

<br><br>

<div class="container" id="main">

    <table class="table table-striped table-bordered">
        <thead>
        <tr>
            <th>First Name</th>
            <th>Last Name</th>
            <th>Role</th>
            <th>Actions</th>
        </tr>
        </thead>
        <tbody>
        <tr>
            <td></td>
            <td></td>
            <td></td>
            <td>
                <a>Edit</a>
                <a>Delete</a>
            </td>
        </tr>
        </tbody>
    </table>
</div>

<script src="/webjars/jquery/jquery.min.js"></script>
<script src="/webjars/bootstrap/js/bootstrap.min.js"></script>
</body>
</html>

커밋 #4 - Vue 매직



이제 pom.xml 파일에 Vue 및 Axios를 추가합니다.

<dependency>
    <groupId>org.webjars</groupId>
    <artifactId>vue</artifactId>
    <version>2.6.11</version>
</dependency>
<dependency>
    <groupId>org.webjars.npm</groupId>
    <artifactId>axios</artifactId>
    <version>0.19.0</version>
</dependency>

그런 다음 REST 컨트롤러(기본적으로 JSON에 대한 응답을 직렬화함)가 역할 목록을 반환합니다.

@RestController
@RequestMapping("/api/v1")
public class RolesController {

    private final RoleRepository roleRepository;

    public RolesController(RoleRepository roleRepository) {
        this.roleRepository = roleRepository;
    }

    @GetMapping("roles")
    public List<Role> list() {
        return roleRepository.findAll();
    }
}

그리고 사용자를 위한 또 다른 것:

@RestController
@RequestMapping("/api/v1")
public class UsersController {

    private final UserRepository userRepository;

    public UsersController(UserRepository userRepository) {
        this.userRepository = userRepository;
    }

    @GetMapping("/users")
    public List<User> list() {
        return userRepository.findAll();
    }
}

마지막으로 roles.html에서 Vue.js가 데이터를 렌더링하고 스크립트를 추가할 섹션을 편집합니다.

<!-- unrelated code omitted for brevity -->
<tr v-for="role in roles">
    <td>{{ role.id }}</td>
    <td>{{ role.name }}</td>
<!-- unrelated code omitted for brevity -->

<!-- Vue.js imports -->
<script src="webjars/vue/vue.min.js"></script>
<script src="webjars/axios/dist/axios.min.js"></script>
<!-- Actual Vue.js script -->
<script>
    var app = new Vue({
        el: '#main',
        data() {
            return {
                roles: null
            }
        },
        mounted(){
            axios
                .get("/api/v1/roles")
                .then(response => (this.roles = response.data))
        },
    })
</script>
users.html에서 동일한 수정이 이루어집니다.

<!-- unrelated code omitted for brevity -->
<tr v-for="user in users">
    <td>{{ user.firstName }}</td>
    <td>{{ user.lastName }}</td>
    <td>{{ user.role.name }}</td>
<!-- unrelated code omitted for brevity -->

<!-- Vue.js imports -->
<script src="webjars/vue/vue.min.js"></script>
<script src="webjars/axios/dist/axios.min.js"></script>
<!-- Actual Vue.js script -->
<script>
    var app = new Vue({
        el: '#main',
        data() {
            return {
                users: null
            }
        },
        mounted(){
            axios
                .get("/api/v1/users")
                .then(response => (this.users = response.data))
        },
    })
</script>



실행 중인 앱을 볼 수 있습니다here(진행 중인 분석이므로 약간 수정됨).

저장소 및 앞서 언급한 커밋도 약간 수정되었습니다here.


브루노드루고윅 / 봄-thymeleaf-vue-crud-예제


Spring Boot, Thymeleaf, Vue.js 및 Axios로 CRUD 예제 프로젝트를 완료하십시오.





AQAP 시리즈



As Quickly As Possible(AQAP)은 제가 흥미롭게 생각하는 것에 대한 일련의 빠른 게시물입니다. 여기에서 빠르게 설명된 기술, 라이브러리 또는 코드를 더 자세히 탐색하기 위해 의견에 대한 토론을 권장하고 참여합니다.

초보자 태그



이 태그를 두 번째로 사용하고 있습니다. 그것을 사용하는 규칙이 있기 때문에 여기에 당신(또는 초보자)이 이해하지 못하는 것이 있거나 내가 당연하게 여겼고 당신(또는 초보자가 :) 그것에 대해 혼란스러워하는 것이 있다면 알려주세요.


Image by Jason King 의해 Pixabay

좋은 웹페이지 즐겨찾기