Spring TH CURD

本文介绍如何使用SpringBoot和Thymeleaf实现增删改查功能,通过实例展示如何搭建环境、定义数据模型、控制器以及视图层,适合初学者快速上手。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1 概述
如今使用Spring boot+thymeleaf开发Web应用程序,开发周期更短,学习周期也短。本节课程技术采用Spring Boot+thymeleaf+ArrayList组合,可以在学员位不了解Spring Data或不使用数据库访问对象的情况仍然学习好 Spring Boot+thymeleaf 开发CURD程序。

2 依赖
在这种情况下,我们将依赖spring-boot-starter-parent进行简单的依赖关系管理,版本控制和插件配置。

<?xml version="1.0" encoding="UTF-8"?>


4.0.0

org.springframework.boot
spring-boot-starter-parent
2.1.6.RELEASE


com.wangshenghua
spring-mvc-curd
0.0.1-SNAPSHOT
spring-mvc-curd
Demo project for Spring Boot

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

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

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>
</dependencies>

<build>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
        </plugin>
    </plugins>
</build>
3 数据模型层 为避免过多的细节,这里还是使用POJO作为数据模型层。学员可以更专注于thymeleaf。

package com.wangshenghua.model;

public class User {

private long id;

private String name;

private String email;

public User() {
}

public User(long id, String name, String email) {
    this.id = id;
    this.name = name;
    this.email = email;
}

public long getId() {
    return id;
}

public void setId(long id) {
    this.id = id;
}

public String getName() {
    return name;
}

public void setName(String name) {
    this.name = name;
}

public String getEmail() {
    return email;
}

public void setEmail(String email) {
    this.email = email;
}

}
4 控制器层
在这一层使用一个类UserController.java却包含数据访问对象(DAO)的功能。

package com.wangshenghua.controller;

import java.util.ArrayList;
import java.util.List;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;

import com.wangshenghua.model.User;

@Controller
public class UserController {

private static List<User> users = new ArrayList<User>();
// 使用List当容器保存数据,来代替数据库

static {
    users.add(new User(1, "黄志燕", "ssss@qq.com"));
    users.add(new User(2, "侯慧聪", "hhhh@qq.com"));
    users.add(new User(3, "王广宏", "gggg@qq.com"));
}

private long getMaxId() {
    long id = 0;
    for (User user : users) {
        if (user.getId() > id)
            id = user.getId();
    }

    return id + 1;
}
 
private User getUser(long id) {
    User user = null ;
    for (User u : users) {
        if (u.getId() == id) {
            user = u;
            break;
        }
    }
     
    return user;
}
 
private void update(User user,long id) {
    for (User u : users) {
        if (u.getId() == id) {
            u.setName(user.getName());
            u.setEmail(user.getEmail());
            break;
        }
    }
}
 
private void delete(long id) {
    for (User u : users) {
        if (u.getId() == id) {
            users.remove(u);
            break;
        }
    }
}
 
@GetMapping("/allUser")
public String allUser(Model model) {
    model.addAttribute("users", users);
    return "list-user";
}

@GetMapping("/adduser")
public String showAddUserForm(Model model) {
    User user = new User();
    user.setId(getMaxId());
    model.addAttribute("user", user);
    return "add-user";
}

@PostMapping("/adduser")
public String addUser(User user, Model model) {

    users.add(user);
     
    return "redirect:/allUser";
}

@GetMapping("/edit/{id}")  //{id}是占位符
public String showUpdateForm(@PathVariable("id") long id, Model model) { //@PathVariable 路径变量
    User user = getUser(id);
    model.addAttribute("user", user);
    return "update-user";
}

@PostMapping("/update/{id}")
public String updateUser(@PathVariable("id") long id, User user, Model model) {
    update(user,id);
    return "redirect:/allUser";
}

@GetMapping("/delete/{id}")
public String deleteUser(@PathVariable("id") long id, Model model) {
    delete(id);
    return "redirect:/allUser";
}

}
@Controller注释表明UserController.java类是一个控制器。

Spring的控制器默认是单实例,因此List users被设计成静态的,使得它在全生命周期可以使用。而且添加一个静态块用于初始部分数据,这里初始了3条用户信息。

接下来的几个方法代替了DAO层的查找、保存、删除方法。

@GetMapping和@PostMapping分别表示get请求和post请求,相当于Servlet中doGet()方法和doPost()方法。这意味着 @GetMapping和@PostMapping 中的值可以一样。

在方法showUpdateForm()上传的注释中出现了{id},它表示一个占位符,表示路径变量的占位符,其中的id可以是别的字符。而紧跟是注释@PathVariable(“id”) long id,用于获取占位符 {id} 实际传递过来的值。

@PathVariable注释用途非常广泛,在查找、修改、删除等方法中都需要用到。

重定向,通过redirect指示重定向到另一个URL。如”redirect:/allUser” 重定向到请求 /allUser

在showAddUserForm方法中,实例化一个User,并设置好id,然后通过Model的实例传递实例User到视图层add-user.html

5 视图层
视图层在使用thymeleaf模板时,视图层的文件都是.html文件。这对前后端分工合作开发非常好友,前端开发人员不需要懂java编程也能参与到Java开发中来。

thymeleaf模板文件在spring boot工程中统一放置在src/main/resources/templates目录里。这个规则很重要,不遵循会出现404的错误。

list-user.html
list-user.html 视图用于遍历所有的用户信息。

用户列表

没有数据

Users

姓名邮箱修改删除
修改删除

添加新用户

th:switch用于判断,与java中的switch一样,这里判断控制器传递过来的数据。th:case="null" 当没有数据时条件,th:case="*" 当有数据时的条件。

th:each="user : ${users}"用于遍历集合里的数据,user是变量,users是控制传递过来的数据。

显示数据使用th:text="${user.name}",user是变量或实例,name是实例的属性。

属性th:href相当于HTML中的a元素的属性href。@{/edit/} 用于指定个相对的URL路径。而 {id}表示路径变量的一个占位符,(id=${user.id}) 用于设置这个id的实际值。

add-user.html
add-user.html视图提供一个表单,用于添加user。

添加用户 th:action同HTML中form元素的action属性一样,指向一个处理表单的URL。

th:object用于与控制器交互,它的值是控制器传递过来的一个数据模型。这个数据模型可以收集表单的字段。

th:field是HTML中input元素的name属性和value属性的结合体,th:field=”*{name}不仅有属性name,还有属性value。属性name的值是name,value的值是表单中输入的值,或控制器传递过来的数据模型的值。

update-user.html
视图update-user.html提供一个修改数据的表单,它同添加用户的视图一样。

修改用户 6 运行程序 spring boot程序使用嵌入式tomcat作为容器,入口函数是main方法。

package com.wangshenghua.config;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication(scanBasePackages = {“com.wangshenghua.*”})
public class SpringMvcCurdApplication {

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

}
这个类在使用STS创建Spring Starter Project时自动生成。

@SpringBootApplication用于指示容器,这是入口处,要运行程序先到这里来。

参数scanBasePackages用于扫描包,它的值是各包名,可以使用能配符*。在多个包的情况下,未指定包扫描的包不会被实例化,不被实例化也就不能在内存里,不能在CPU里执行。

右击工程,在弹出的菜单中选择【Run as】【Spring Boot App】启动工程,在浏览器地址栏输入http://localhost:8080即可访问本程序。

7 总结
本节课程使用Spring Boot和thymeleaf技术实现一个增、删、改、查的小程序。程序虽小,用到的技术却是以后复杂应用的基石。学员位重点掌握控制层各方法的写及视图如何遍历数据、表单的使用。

本节课程源码已经上传到github,可以前往下载。

<think>好的,用户想要了解Spring框架中关于CRUD操作的实现方式或示例。我需要先整理Spring框架中实现CRUD的基本流程和相关组件。 首先,CRUD操作通常涉及数据访问层,Spring Data JPA是常用的工具。记得用户提到的引用[4]提到Repository的问题,可能需要说明如何定义Repository接口。需要提到创建继承JpaRepository的接口,这样会自动获得基本的CRUD方法。 然后,服务层会调用Repository的方法,处理业务逻辑。引用[1]中的@SpringBootTest和UserService的例子,可以结合这个来说明服务层的实现。需要给出@Service注解的类,并注入Repository。 控制器层处理HTTP请求,使用@RestController和@RequestMapping注解。可能需要展示如何编写RESTful API的各个方法,比如@GetMapping、@PostMapping等。 配置方面,引用[2]提到添加依赖,所以需要列出Spring Boot Starter Data JPA和H2数据库的依赖,这样用户可以直接配置。同时,application.properties中的配置也很重要,比如启用H2控制台。 最后,单元测试部分可以参考引用[1]中的示例,使用@SpringBootTest来测试服务层的方法是否正确执行CRUD操作。 需要检查各部分的代码示例是否正确,确保语法正确,比如Repository接口的泛型参数,服务层的注解是否正确。同时,注意用户要求的中文回答,以及行内公式的格式,但在这个问题中可能涉及较少数学内容,但如果有提到算法或性能分析,可能需要使用LaTeX格式。 可能还需要考虑用户是否了解Spring Boot的基本结构,所以在示例中需要明确分层:实体类、Repository、Service、Controller,以及配置和测试。确保每一步都有代码示例,并解释关键注解的作用,比如@Entity、@Service、@Autowired等。 另外,用户提供的引用[3]提到Spring的发展历史和核心价值,可能在回答中可以简要提到Spring简化企业级开发的优势,但主要聚焦在CRUD实现的具体步骤。 最后,生成的相关问题需要围绕CRUD操作的扩展,比如验证、异常处理、分页等,以及与其他技术的整合,确保问题对用户有进一步的帮助。</think>以下是通过Spring Framework实现CRUD操作的完整示例说明,包含分层架构和关键代码实现: ### 一、基础环境配置 1. **Maven依赖配置**(引用[2]): ```xml <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency> <dependency> <groupId>com.h2database</groupId> <artifactId>h2</artifactId> <scope>runtime</scope> </dependency> ``` 2. **application.properties配置**: ```properties spring.datasource.url=jdbc:h2:mem:testdb spring.h2.console.enabled=true spring.jpa.hibernate.ddl-auto=update ``` ### 二、实体类定义 ```java @Entity public class User { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private String name; private String email; // 省略构造函数和getter/setter } ``` ### 三、Repository层实现 ```java public interface UserRepository extends JpaRepository<User, Long> { // 自动继承以下CRUD方法: // save(S entity) - 创建/更新 // findById(ID id) - 读取 // delete(T entity)- 删除 // findAll() - 查询所有 } ``` ### 四、Service层实现 ```java @Service public class UserService { @Autowired private UserRepository repository; public User createUser(User user) { return repository.save(user); } public Optional<User> getUser(Long id) { return repository.findById(id); } public List<User> getAllUsers() { return repository.findAll(); } public void deleteUser(Long id) { repository.deleteById(id); } } ``` ### 五、Controller层实现 ```java @RestController @RequestMapping("/api/users") public class UserController { @Autowired private UserService userService; @PostMapping public User createUser(@RequestBody User user) { return userService.createUser(user); } @GetMapping("/{id}") public ResponseEntity<User> getUser(@PathVariable Long id) { return userService.getUser(id) .map(ResponseEntity::ok) .orElse(ResponseEntity.notFound().build()); } @DeleteMapping("/{id}") public void deleteUser(@PathVariable Long id) { userService.deleteUser(id); } } ``` ### 六、单元测试示例(引用[1]) ```java @SpringBootTest class UserServiceTest { @Autowired private UserService service; @Test void testCRUDOperations() { User user = new User("Alice", "alice@example.com"); User saved = service.createUser(user); assertNotNull(saved.getId()); Optional<User> found = service.getUser(saved.getId()); assertTrue(found.isPresent()); service.deleteUser(saved.getId()); assertFalse(service.getUser(saved.getId()).isPresent()); } } ``` ### 关键特性说明: 1. **数据访问抽象**:通过JpaRepository自动获得18个CRUD方法[^4] 2. **事务管理**:@Transactional注解默认在服务层启用 3. **依赖注入**:通过@Autowired实现组件解耦 4. **REST支持**:@RestController自动处理JSON序列化
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值