环境准备
- JDK 1.8 及以上
- SpringBoot 2.5.5 及以上
- MySQL 5.7 及以上
- Maven
- IntelliJ IDEA (可选)
创建项目
我们使用 IntelliJ IDEA 创建一个 Spring Boot Web 项目。
-
打开 IntelliJ IDEA,点击菜单栏的 “File”,选择 “New”,然后选择 “Project”。
-
在向导中选择 “Spring Initializr”,然后点击 Next。
-
在 Spring Initializr 页面中,填写项目信息。
- Group:自己定义
- Artifact:自己定义
- Dependencies:选择 “Spring Web”、“Spring Data JPA” 和 “MySQL Driver”,然后点击 Next。
- Metadata:自己定义
然后点击 Finish,等待项目创建完成。
数据库配置
在 application.properties
文件中添加以下配置:
spring.datasource.url=jdbc:mysql://localhost:3306/test?useSSL=false&serverTimezone=UTC&allowPublicKeyRetrieval=true
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.jpa.database-platform=org.hibernate.dialect.MySQL5InnoDBDialect
spring.jpa.hibernate.ddl-auto=create
实现用户表
创建用户实体
我们先创建一个用户实体类 User
,并使用 JPA 注解标记对应数据库的表名和字段名。
@Entity
@Table(name = "user")
public class User implements Serializable {@Id@GeneratedValue(strategy = GenerationType.IDENTITY)private Long id;private String name;private Integer age;@Column(name = "create_time")private LocalDateTime createTime;@Column(name = "update_time")private LocalDateTime updateTime;// Getter 和 Setter 略
}
创建用户 Repository
创建一个接口 UserRepository
,并继承 JpaRepository
接口。
public interface UserRepository extends JpaRepository<User, Long> {
}
创建用户 Service
创建一个 Service 接口 UserService
,定义对用户操作的方法。
public interface UserService {User save(User user);void deleteById(Long id);User findById(Long id);List<User> findAll();
}
创建一个 Service 实现类 UserServiceImpl
,实现 Service 接口,对用户的增删改查操作进行具体实现。
@Service
public class UserServiceImpl implements UserService {private final UserRepository userRepository;@Autowiredpublic UserServiceImpl(UserRepository userRepository) {this.userRepository = userRepository;}@Overridepublic User save(User user) {LocalDateTime now = LocalDateTime.now();user.setCreateTime(now);user.setUpdateTime(now);return userRepository.save(user);}@Overridepublic void deleteById(Long id) {userRepository.deleteById(id);}@Overridepublic User findById(Long id) {return userRepository.findById(id).orElse(null);}@Overridepublic List<User> findAll() {return userRepository.findAll();}
}
实现 Controller
添加页面
我们需要先添加前端页面,这里使用 Freemarker 模板进行实现。
在 resources/templates/
目录下创建名为 user.ftl
的文件,并填写以下代码:
<!DOCTYPE html>
<html>
<head><meta charset="UTF-8"><title>用户管理</title>
</head>
<body><h2>用户管理</h2><form><input type="hidden" id="id" name="id"/><br/>用户名:<input type="text" id="name" name="name" required="required"/><br/>年龄:<input type="number" id="age" name="age" required="required"/><br/><br/><button type="button" id="save">保存</button></form><table><tr><th>id</th><th>name</th><th>age</th><th>create_time</th><th>update_time</th><th>操作</th></tr><#list userList as user><tr><td>${user.id}</td><td>${user.name}</td><td>${user.age}</td><td>${user.createTime}</td><td>${user.updateTime}</td><td><button type="button" class="edit" data-id="${user.id}">编辑</button><button type="button" class="delete" data-id="${user.id}">删除</button></td></tr></#list></table><script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.min.js"></script><script>$(function() {function clearForm() {$('input[type="text"],input[type="number"]').val('');$('input[type="hidden"]').val(0);}function listUser() {$.get('/user', function (data) {$('.user-table').replaceWith(data);});}$('form #save').click(function () {var id = $('form #id').val();var formData = $('form').serializeArray();var user = {};$.each(formData, function (_, kv) {user[kv.name] = kv.value;});user.id = id;$.ajax('/user', {data: JSON.stringify(user),contentType: 'application/json',type: (id === '0') ? 'POST' : 'PUT',success: function () {clearForm();listUser();}});});$(document).on('click', '.edit', function () {var id = $(this).data('id');$.get('/user/' + id, function (data) {$.each(data, function (key, value) {$('form #' + key).val(value);});});});$(document).on('click', '.delete', function () {var id = $(this).data('id');$.ajax('/user/' + id, {type: 'DELETE',success: function () {listUser();}});});listUser();});</script>
</body>
</html>
创建 Controller
创建一个 Controller 类 UserController
,并添加对用户增删改查的对应操作。同时,使用 @Controller
和 @ResponseBody
注解实现对前端页面请求的响应,并使用 @Autowired
注解自动注入 UserService。
@Controller
@RequestMapping("/user")
public class UserController {private final UserService userService;@Autowiredpublic UserController(UserService userService) {this.userService = userService;}@GetMappingpublic String index(Model model) {List<User> userList = userService.findAll();model.addAttribute("userList", userList);return "user";}@PostMapping@ResponseBodypublic User add(@RequestBody User user) {return userService.save(user);}@PutMapping("/{id}")@ResponseBodypublic User update(@PathVariable("id") Long id, @RequestBody User user) {User oldUser = userService.findById(id);if (oldUser == null) {return null;}oldUser.setName(user.getName());oldUser.setAge(user.getAge());oldUser.setUpdateTime(LocalDateTime.now());return userService.save(oldUser);}@DeleteMapping("/{id}")@ResponseBodypublic void delete(@PathVariable("id") Long id) {userService.deleteById(id);}@GetMapping("/{id}")@ResponseBodypublic User find(@PathVariable("id") Long id) {return userService.findById(id);}
}
测试
启动应用程序,在浏览器中访问 http://localhost:8080/user
,即可看到用户的增删改查界面。在该界面中,您可以添加、修改、删除和查询用户信息。同时,您也可以查看完整的工程目录结构。
工程目录结构
spring-boot-demo/├─src/│ ├─main/│ │ ├─java/│ │ │ └─com/│ │ │ └─example/│ │ │ ├─controller/│ │ │ │ └─UserController.java│ │ │ ├─domain/│ │ │ │ └─User.java│ │ │ ├─repository/│ │ │ │ └─UserRepository.java│ │ │ ├─service/│ │ │ │ ├─impl/│ │ │ │ │ └─UserServiceImpl.java│ │ │ │ └─UserService.java│ │ │ └─SpringBootDemoApplication.java│ │ └─resources/│ │ ├─static/│ │ └─templates/│ │ └─user.ftl│ └─test/└─pom.xml
完整代码
为方便您的参考,这里提供一个完整的项目代码。其中,可以直接使用自己的数据库信息进行测试。
User.java
package com.example.domain;import javax.persistence.*;
import java.io.Serializable;
import java.time.LocalDateTime;@Entity
@Table(name = "user")
public class User implements Serializable {@Id@GeneratedValue(strategy = GenerationType.IDENTITY)private Long id;private String name;private Integer age;@Column(name = "create_time")private LocalDateTime createTime;@Column(name = "update_time")private LocalDateTime updateTime;// Getter 和 Setter 略
}
UserRepository.java
package com.example.repository;import com.example.domain.User;
import org.springframework.data.jpa.repository.JpaRepository;public interface UserRepository extends JpaRepository<User, Long> {
}
UserService.java
package com.example.service;import com.example.domain.User;import java.util.List;public interface UserService {User save(User user);void deleteById(Long id);User findById(Long id);List<User> findAll();
}
UserServiceImpl.java
package com.example.service.impl;import com.example.domain.User;
import com.example.repository.UserRepository;
import com.example.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;import java.time.LocalDateTime;
import java.util.List;@Service
public class UserServiceImpl implements UserService {private final UserRepository userRepository;@Autowiredpublic UserServiceImpl(UserRepository userRepository) {this.userRepository = userRepository;}@Overridepublic User save(User user) {LocalDateTime now = LocalDateTime.now();user.setCreateTime(now);user.setUpdateTime(now);return userRepository.save(user);}@Overridepublic void deleteById(Long id) {userRepository.deleteById(id);}@Overridepublic User findById(Long id) {return userRepository.findById(id).orElse(null);}@Overridepublic List<User> findAll() {return userRepository.findAll();}
}
UserController.java
package com.example.controller;import com.example.domain.User;
import com.example.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;import java.time.LocalDateTime;
import java.util.List;@Controller
@RequestMapping("/user")
public class UserController {private final UserService userService;@Autowiredpublic UserController(UserService userService) {this.userService = userService;}@GetMappingpublic String index(Model model) {List<User> userList = userService.findAll();model.addAttribute("userList", userList);return "user";}@PostMapping@ResponseBodypublic User add(@RequestBody User user) {return userService.save(user);}@PutMapping("/{id}")@ResponseBodypublic User update(@PathVariable("id") Long id, @RequestBody User user) {User oldUser = userService.findById(id);if (oldUser == null) {return null;}oldUser.setName(user.getName());oldUser.setAge(user.getAge());oldUser.setUpdateTime(LocalDateTime.now());return userService.save(oldUser);}@DeleteMapping("/{id}")@ResponseBodypublic void delete(@PathVariable("id") Long id) {userService.deleteById(id);}@GetMapping("/{id}")@ResponseBodypublic User find(@PathVariable("id") Long id) {return userService.findById(id);}
}
pom.xml
<dependencies><!-- Spring Boot 数据 JPA 相关依赖 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-jpa</artifactId></dependency><!-- Freemarker 模板引擎依赖 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-freemarker</artifactId></dependency><!-- MySQL 数据库驱动依赖 --><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId></dependency><!-- Spring Boot Web 依赖 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency>
</dependencies>
SpringBootDemoApplication.java
package com.example;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplication
public class SpringBootDemoApplication {public static void main(String[] args) {SpringApplication.run(SpringBootDemoApplication.class, args);}
}
application.properties
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf-8&useSSL=false
spring.datasource.username=root
spring.datasource.password=root# 让 Hibernate 自动创建数据库表结构
spring.jpa.hibernate.ddl-auto=create
# 设置 Hibernate 方言
spring.jpa.database-platform=org.hibernate.dialect.MySQL8Dialect
user.ftl
<!DOCTYPE html>
<html lang="zh-CN">
<head><meta charset="UTF-8"><title>用户管理系统</title><style>body {background-color: #F0F0F0;}.container {width: 1200px;margin: 20px auto;padding: 20px;border-radius: 5px;background-color: #FFFFFF;box-shadow: 0 0 5px #999999;}h1 {text-align: center;margin-bottom: 30px;}.add {margin-bottom: 20px;}.add input[type='text'], .add input[type='number'] {width: 150px;padding: 5px;border-radius: 5px;border: 1px solid #CCCCCC;margin-right: 10px;}.add button {padding: 5px 10px;border-radius: 5px;border: 1px solid #CCCCCC;background-color: #FFFFFF;cursor: pointer;}table {width: 100%;border-collapse: collapse;text-align: center;margin-bottom: 30px;}th {background-color: #F5F5F5;padding: 10px;border-bottom: 1px solid #CCCCCC;}td {padding: 10px;border-bottom: 1px solid #CCCCCC;}.btn-group {margin-bottom: 20px;}.btn-group button {padding: 5px 10px;border-radius: 5px;border: 1px solid #CCCCCC;background-color: #FFFFFF;cursor: pointer;margin-right: 10px;}</style>
</head>
<body>
<div class="container"><h1>用户管理系统</h1><div class="add"><input type="text" id="name" placeholder="姓名"><input type="number" id="age" placeholder="年龄"><button onclick="addUser()">添加用户</button></div><table><thead><tr><th>ID</th><th>姓名</th><th>年龄</th><th>创建时间</th><th>更新时间</th><th>操作</th></tr></thead><tbody><#list userList as user><tr><td>${user.id}</td><td>${user.name}</td><td>${user.age}</td><td>${user.createTime?string("yyyy-MM-dd HH:mm:ss")}</td><td>${user.updateTime?string("yyyy-MM-dd HH:mm:ss")}</td><td><div class="btn-group"><button onclick="editUser(${user.id})">编辑</button><button onclick="deleteUser(${user.id})">删除</button></div></td></tr></#list></tbody></table>
</div><script>function addUser() {let name = document.getElementById("name").value;let age = document.getElementById("age").value;let xhr = new XMLHttpRequest();xhr.open("POST", "/user");xhr.setRequestHeader("Content-Type", "application/json");xhr.onreadystatechange = function () {if (xhr.readyState === XMLHttpRequest.DONE) {if (xhr.status === 200 || xhr.status === 201) {location.reload();} else {alert("添加用户失败!");}}}xhr.send(JSON.stringify({name, age}));}function editUser(id) {let name = prompt("请输入姓名:");let age = prompt("请输入年龄:");let xhr = new XMLHttpRequest();xhr.open("PUT", `/user/${id}`);xhr.setRequestHeader("Content-Type", "application/json");xhr.onreadystatechange = function () {if (xhr.readyState === XMLHttpRequest.DONE) {if (xhr.status === 200 || xhr.status === 201) {location.reload();} else {alert("编辑用户失败!");}}}xhr.send(JSON.stringify({name, age}));}function deleteUser(id) {if (confirm("确定删除该用户吗?")) {let xhr = new XMLHttpRequest();xhr.open("DELETE", `/user/${id}`);xhr.onreadystatechange = function () {if (xhr.readyState === XMLHttpRequest.DONE) {if (xhr.status === 200 || xhr.status === 201) {location.reload();} else {alert("删除用户失败!");}}}xhr.send();}}
</script>
</body>
</html>
总结
虽然现在前后端分离的场景比较普遍,前端有很多流行的框架,如Vue、Angular、React等,但是上面介绍的基于SpringBoot和Freemarker的用户管理系统对于初学者学习来说仍然是一份非常好的示例。
通过这个例子,我们可以学习到如何使用Spring Boot快速搭建一个Web应用,如何使用JPA进行数据持久化,以及如何使用Freemarker模板引擎来渲染页面。同时,这个例子也展示了一个最基本的CRUD应用,其中包括增加、删除、修改和查询用户。
无论是在学习过程中还是实际开发中,了解这些基本的概念和用法都是非常重要的。因此,我认为这个例子对于初学者来说是非常有用的。