springboot-jpa的实现操作

时间:2022-10-09 09:28:28

JPA全称为Java Persistence API(Java持久层API),它是Sun公司在JavaEE 5中提出的Java持久化规范。

它为Java开发人员提供了一种对象/关联映射工具,来管理Java应用中的关系数据,JPA吸取了目前Java持久化技术的优点,旨在规范、简化Java对象的持久化工作。

JPA对于单表的或者简单的SQL查询非常友好,甚至可以说非常智能。他为你准备好了大量的拿来即用的持久层操作方法。甚至只要写findByName这样一个接口方法,他就能智能的帮你执行根据名称查找实体类对应的表数据,完全不用写SQL。

它相对于mybatis来说不用写xml等配置,简直方便的不行,对于我们开发者来说,谁更简单,开发效率更高,我们就喜欢谁(不喜欢不行,看看产品经理手里的菜刀)!!!

这时候mybatis就不服了,我确实需要写一大堆乱七八糟的xml,但是也可以用注解啊。

还不是要写sql,总是一写增删改查sql,有没有把这些常见的增删改查全部封装起来,我们直接调用api,sql让它们自动组装就好了,说实话我自己封装了一个基于mybatis的组件,常见的增删改查,自己组装成sql去查询,后来由于没有oracle,sqlserver的数据库环境,对这些数据库的时间等等函数支持不好,又有jpa和mybatisplus这些现有的,我也就偷懒了

好了我们之前有实现过springboot-mybatis

springboot-mybatisplus的整合,现在就来实现一下jpa的,你们看看哪个比较方便好用,可以自己用用看

springboot-jpa的实现操作

这是我实现的demo预览

由于我想看到效果,又不想装postman来测试,我就集成了swagger

springboot-jpa的实现操作

最终效果如上图

好了,我直接放代码了

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <project xmlns="http://maven.apache.org/POM/4.0.0"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  5. <modelVersion>4.0.0</modelVersion>
  6.  
  7. <groupId>com.zkb</groupId>
  8. <artifactId>spring-data-jpa</artifactId>
  9. <version>1.0-SNAPSHOT</version>
  10. <build>
  11. <plugins>
  12. <plugin>
  13. <groupId>org.apache.maven.plugins</groupId>
  14. <artifactId>maven-compiler-plugin</artifactId>
  15. <configuration>
  16. <source>8</source>
  17. <target>8</target>
  18. </configuration>
  19. </plugin>
  20. </plugins>
  21. </build>
  22. <dependencies>
  23. <dependency>
  24. <groupId>org.springframework.boot</groupId>
  25. <artifactId>spring-boot-starter-web</artifactId>
  26. <version>2.1.1.RELEASE</version>
  27. </dependency>
  28.  
  29. <dependency>
  30. <groupId>org.springframework.boot</groupId>
  31. <artifactId>spring-boot-starter-data-jpa</artifactId>
  32. <version>2.1.1.RELEASE</version>
  33. </dependency>
  34.  
  35. <dependency>
  36. <groupId>mysql</groupId>
  37. <artifactId>mysql-connector-java</artifactId>
  38. <version>8.0.18</version>
  39. </dependency>
  40.  
  41. <dependency>
  42. <groupId>org.projectlombok</groupId>
  43. <artifactId>lombok</artifactId>
  44. <version>1.18.12</version>
  45. </dependency>
  46.  
  47. <dependency>
  48. <groupId>org.springframework.boot</groupId>
  49. <artifactId>spring-boot-devtools</artifactId>
  50. <version>2.0.4.RELEASE</version>
  51. </dependency>
  52.  
  53. <dependency>
  54. <groupId>org.springframework.boot</groupId>
  55. <artifactId>spring-boot-starter-test</artifactId>
  56. <version>2.1.2.RELEASE</version>
  57. <scope>test</scope>
  58. </dependency>
  59. <dependency>
  60. <groupId>com.alibaba</groupId>
  61. <artifactId>druid</artifactId>
  62. <version>1.0.31</version>
  63. </dependency>
  64. <dependency>
  65. <groupId>org.junit.jupiter</groupId>
  66. <artifactId>junit-jupiter</artifactId>
  67. <version>RELEASE</version>
  68. <scope>compile</scope>
  69. </dependency>
  70. <dependency>
  71. <groupId>org.junit.jupiter</groupId>
  72. <artifactId>junit-jupiter</artifactId>
  73. <version>RELEASE</version>
  74. <scope>compile</scope>
  75. </dependency>
  76.  
  77. <dependency>
  78. <groupId>org.slf4j</groupId>
  79. <artifactId>slf4j-api</artifactId>
  80. <version>1.7.25</version>
  81. </dependency>
  82. <dependency>
  83. <groupId>org.springframework.boot</groupId>
  84. <artifactId>spring-boot-test</artifactId>
  85. <version>2.2.2.RELEASE</version>
  86. <scope>compile</scope>
  87. </dependency>
  88.  
  89. <dependency>
  90. <groupId>io.springfox</groupId>
  91. <artifactId>springfox-swagger2</artifactId>
  92. <version>2.9.2</version>
  93. <exclusions>
  94. <exclusion>
  95. <groupId>io.swagger</groupId>
  96. <artifactId>swagger-annotations</artifactId>
  97. </exclusion>
  98. <exclusion>
  99. <groupId>io.swagger</groupId>
  100. <artifactId>swagger-models</artifactId>
  101. </exclusion>
  102. </exclusions>
  103. </dependency>
  104. <dependency>
  105. <groupId>io.swagger</groupId>
  106. <artifactId>swagger-annotations</artifactId>
  107. <version>1.5.22</version>
  108. </dependency>
  109.  
  110. <dependency>
  111. <groupId>io.swagger</groupId>
  112. <artifactId>swagger-models</artifactId>
  113. <version>1.5.22</version>
  114. </dependency>
  115. <!-- swagger-ui -->
  116. <dependency>
  117. <groupId>io.springfox</groupId>
  118. <artifactId>springfox-swagger-ui</artifactId>
  119. <version>2.9.2</version>
  120. </dependency>
  121.  
  122. <dependency>
  123. <groupId>com.github.xiaoymin</groupId>
  124. <artifactId>swagger-bootstrap-ui</artifactId>
  125. <version>1.9.1</version>
  126. </dependency>
  127. </dependencies>
  128.  
  129. </project>
  1. server:
  2. port: 5001
  3. spring:
  4. datasource:
  5. type: com.alibaba.druid.pool.DruidDataSource #Druid 是阿里巴巴开源平台上一个数据库连接池实现,结合了 C3P0、DBCP、PROXOOL 等 DB 池的优点,同时加入了日志监控
  6. driver-class-name: com.mysql.cj.jdbc.Driver
  7. url: jdbc:mysql://localhost:3306/test-demo?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=UTC&autoReconnect=true&failOverReadOnly=false&zeroDateTimeBehavior=convertToNull
  8. username: root
  9. password: root
  10. dbcp2:
  11. min-idle: 5
  12. initial-size: 5
  13. max-total: 5
  14. max-wait-millis: 200
  15. jpa:
  16. database: mysql
  17. database-platform: org.hibernate.dialect.MySQL5InnoDBDialect
  18. show-sql: true
  19. hibernate:
  20. ddl-auto: update
  1. package com.zkb.entity;
  2. import com.fasterxml.jackson.databind.annotation.JsonSerialize;
  3. import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
  4. import io.swagger.annotations.ApiModel;
  5. import io.swagger.annotations.ApiModelProperty;
  6. import lombok.Data;
  7. import javax.persistence.*;
  8. /**
  9. * 实体类
  10. */
  11. @Entity
  12. @Table(name = "t_user")
  13. @Data
  14. @ApiModel(value = "用户信息", description = "用户信息")
  15. public class User {
  16. @Id
  17. @GeneratedValue(strategy = GenerationType.IDENTITY)
  18. @ApiModelProperty(value = "主键")
  19. @JsonSerialize(using = ToStringSerializer.class)
  20. private Long id;
  21.  
  22. @Column(name = "username")
  23. @ApiModelProperty(value = "用户名")
  24. private String username;
  25.  
  26. @Column(name = "password")
  27. @ApiModelProperty(value = "密码")
  28. private String password;
  29.  
  30. }
  1. package com.zkb.dao;
  2. import com.zkb.entity.User;
  3. import org.springframework.data.jpa.repository.JpaRepository;
  4. public interface UserRepository extends JpaRepository<User,Long> {
  5. }
  1. package com.zkb.service;
  2. import com.zkb.entity.User;
  3. import java.util.List;
  4. public interface UserService {
  5. public void deleteUser(Long id);
  6. List<User> getList();
  7. }
  1. package com.zkb.service.impl;
  2. import com.zkb.dao.UserRepository;
  3. import com.zkb.entity.User;
  4. import com.zkb.service.UserService;
  5. import org.springframework.beans.factory.annotation.Autowired;
  6. import org.springframework.stereotype.Service;
  7. import java.util.List;
  8. @Service
  9. public class UserServiceImpl implements UserService {
  10.  
  11. @Autowired
  12. private UserRepository userRepository;
  13.  
  14. @Override
  15. public void deleteUser(Long id) {
  16. System.out.println(userRepository);
  17. userRepository.deleteById(id);
  18. }
  19.  
  20. @Override
  21. public List<User> getList() {
  22. return userRepository.findAll();
  23. }
  24. }
  1. package com.zkb.controller;
  2. import com.zkb.entity.User;
  3. import com.zkb.service.UserService;
  4. import io.swagger.annotations.Api;
  5. import io.swagger.annotations.ApiOperation;
  6. import org.springframework.beans.factory.annotation.Autowired;
  7. import org.springframework.web.bind.annotation.PostMapping;
  8. import org.springframework.web.bind.annotation.RequestMapping;
  9. import org.springframework.web.bind.annotation.RequestParam;
  10. import org.springframework.web.bind.annotation.RestController;
  11. import java.util.List;
  12. @RestController
  13. @RequestMapping("/user")
  14. @Api(value = "user",tags = "user")
  15. public class UserController {
  16.  
  17. @Autowired
  18. private UserService userService;
  19.  
  20. @PostMapping("/del")
  21. @ApiOperation(value="删除",notes = "删除")
  22. public String delete(@RequestParam("id") Long id){
  23. userService.deleteUser(id);
  24. return "true";
  25. }
  26.  
  27. @PostMapping("/getList")
  28. @ApiOperation(value="查询所有",notes = "查询所有")
  29. public List<User> getList(){
  30. return userService.getList();
  31. }
  32. }
  1. package com.zkb.conf;
  2. import io.swagger.annotations.ApiOperation;
  3. import io.swagger.models.auth.In;
  4. import org.springframework.context.annotation.Bean;
  5. import org.springframework.context.annotation.Configuration;
  6. import springfox.documentation.builders.ApiInfoBuilder;
  7. import springfox.documentation.builders.PathSelectors;
  8. import springfox.documentation.builders.RequestHandlerSelectors;
  9. import springfox.documentation.service.ApiInfo;
  10. import springfox.documentation.service.ApiKey;
  11. import springfox.documentation.service.Contact;
  12. import springfox.documentation.spi.DocumentationType;
  13. import springfox.documentation.spring.web.plugins.Docket;
  14. import springfox.documentation.swagger2.annotations.EnableSwagger2;
  15. import java.util.Arrays;
  16. import java.util.List;
  17. @Configuration
  18. @EnableSwagger2
  19. public class SwaggerApp {
  20. @Bean
  21. public Docket createRestApi1() {
  22. return new Docket(DocumentationType.SWAGGER_2).enable(true).apiInfo(apiInfo()).select()
  23. .apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class))
  24. .apis(RequestHandlerSelectors.basePackage("com.zkb.controller"))
  25. .paths(PathSelectors.any()).build().securitySchemes(apiKeyList()).groupName("接口中心");
  26. }
  27.  
  28. private ApiInfo apiInfo() {
  29. return new ApiInfoBuilder()
  30. .title("API")
  31. .contact(new Contact("XXXXX", "http://XXXXXX.XXXX/", ""))
  32. .version("1.0")
  33. .description("API 描述")
  34. .build();
  35. }
  36.  
  37. private List<ApiKey> apiKeyList() {
  38. return Arrays.asList(new ApiKey("登录token", "token", In.HEADER.name()),
  39. new ApiKey("设备类型(android,ios,pc)---必填", "deviceType", In.HEADER.name()));
  40. }
  41. }
  1. package com.zkb;
  2. import org.springframework.boot.SpringApplication;
  3. import org.springframework.boot.autoconfigure.SpringBootApplication;
  4. import springfox.documentation.swagger2.annotations.EnableSwagger2;
  5. @SpringBootApplication
  6. @EnableSwagger2
  7. public class App {
  8. public static void main(String[] args) {
  9. SpringApplication.run(App.class,args);
  10. }
  11. }
  1. CREATE TABLE `t_user` (
  2. `id` bigint NOT NULL AUTO_INCREMENT,
  3. `username` varchar(50) COLLATE utf8mb4_general_ci DEFAULT NULL,
  4. `password` varchar(50) COLLATE utf8mb4_general_ci DEFAULT NULL,
  5. PRIMARY KEY (`id`) USING BTREE
  6. ) ENGINE=InnoDB AUTO_INCREMENT=1214893367637352451 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;

非常简单的一张表,注意数据库名称

springboot-jpa的实现操作

到这里就已经实现了一个非常简单的jpa demo了

当然我这里只是指路,让知怎么用

补充:SpringBoot使用JPA实现增删查改

一、运行环境

SpringBoot2.3.0

JDK1.8

IDEA2020.1.2

MySQL5.7

二、依赖及应用程序配置

  1. <dependency>
  2. <groupId>org.springframework.boot</groupId>
  3. <artifactId>spring-boot-starter-data-jpa</artifactId>
  4. </dependency>
  5. <dependency>
  6. <groupId>org.springframework.boot</groupId>
  7. <artifactId>spring-boot-starter-thymeleaf</artifactId>
  8. </dependency>
  9. <dependency>
  10. <groupId>org.springframework.boot</groupId>
  11. <artifactId>spring-boot-starter-validation</artifactId>
  12. </dependency>
  13. <dependency>
  14. <groupId>org.springframework.boot</groupId>
  15. <artifactId>spring-boot-starter-web</artifactId>
  16. </dependency>
  17. <dependency>
  18. <groupId>mysql</groupId>
  19. <artifactId>mysql-connector-java</artifactId>
  20. <scope>runtime</scope>
  21. </dependency>
  22. <dependency>
  23. <groupId>org.projectlombok</groupId>
  24. <artifactId>lombok</artifactId>
  25. <optional>true</optional>
  26. </dependency>
  27. <dependency>
  28. <groupId>org.springframework.boot</groupId>
  29. <artifactId>spring-boot-starter-test</artifactId>
  30. <scope>test</scope>
  31. <exclusions>
  32. <exclusion>
  33. <groupId>org.junit.vintage</groupId>
  34. <artifactId>junit-vintage-engine</artifactId>
  35. </exclusion>
  36. </exclusions>
  37. </dependency>

1、升级到SpringBoot2.2,spring-boot-starter-test默认使用JUnit 5作为单元测试框架 ,写单元测试时注解@RunWith(Spring.class)升级为@ExtendWith(SpringExtension.class)

2、升级到SpringBoot2.3,hibernate-validator从spring-boot-starter-web移除,需要单独引入

3、升级到SpringBoot2.3,MySQL驱动由com.mysql.jdbc.Driver变更为com.mysql.cj.jdbc.Driver;同时,数据源url需要添加serverTimezone=UTC&useSSL=false参数

3、升级到SpringBoot2.x,默认不自动注入HiddenHttpMethodFilter,需要设置spring.mvc.hiddenmethod.filter.enabled=true开启PUT、DELETE方法支持

应用程序配置如下:

  1. spring.application.name=springbootjpa
  2. management.endpoints.jmx.exposure.include=*
  3. management.endpoints.web.exposure.include=*
  4. management.endpoint.health.show-details=always
  5. # 应用服务 WEB 访问端口
  6. server.port=8080
  7. # Actuator Web 访问端口
  8. management.server.port=8081
  9. # mysql setting
  10. spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
  11. spring.datasource.url=jdbc:mysql://localhost:3306/springbootjpa?serverTimezone=UTC&useSSL=false
  12. spring.datasource.username=username
  13. spring.datasource.password=password
  14. # JPA setting
  15. spring.jpa.properties.hibernate.hbm2ddl.auto=update
  16. spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5InnoDBDialect
  17. spring.jpa.show-sql=true
  18. # thymeleaf setting
  19. spring.thymeleaf.cache=false
  20. # delete、put方法支持
  21. spring.mvc.hiddenmethod.filter.enabled=true

三、定义实体

使用@Entity标记实体类

  1. import lombok.Data;
  2. import javax.persistence.*;
  3. import javax.validation.constraints.NotEmpty;
  4. import java.io.Serializable;
  5. @Entity
  6. @Data
  7. public class Article extends BaseEntity implements Serializable {
  8. @Id
  9. @GeneratedValue(strategy = GenerationType.IDENTITY)
  10. private Long id;
  11. @Column(nullable = false, unique = true)
  12. @NotEmpty(message = "标题不能为空")
  13. private String title;
  14. @Column(nullable = false)
  15. private String body;
  16. }

为了自动添加创建日期、修改日期、创建人及修改人,我们把创建、修改信息放到父类中由实体类继承,并开启SpringBoot的自动审计功能,将创建/修改信息自动注入

1、定义实体类的父类,@CreatedDate、@LastModifiedDate、@CreatedBy、@LastModifiedBy标注相应字段

  1. import org.hibernate.annotations.Columns;
  2. import org.springframework.data.annotation.CreatedBy;
  3. import org.springframework.data.annotation.CreatedDate;
  4. import org.springframework.data.annotation.LastModifiedBy;
  5. import org.springframework.data.annotation.LastModifiedDate;
  6. import org.springframework.data.jpa.domain.support.AuditingEntityListener;
  7. import javax.persistence.Column;
  8. import javax.persistence.EntityListeners;
  9. import javax.persistence.MappedSuperclass;
  10. @MappedSuperclass
  11. @EntityListeners(AuditingEntityListener.class)
  12. public class BaseEntity {
  13. @CreatedDate
  14. private Long createTime;
  15. @LastModifiedDate
  16. private Long updateTime;
  17.  
  18. @Column(name = "create_by")
  19. @CreatedBy
  20. private String createBy;
  21. @Column(name = "lastmodified_by")
  22. @LastModifiedBy
  23. private String lastmodifiedBy;
  24.  
  25. public Long getCreateTime() {
  26. return createTime;
  27. }
  28. public void setCreateTime(Long createTime) {
  29. this.createTime = createTime;
  30. }
  31. public Long getUpdateTime() {
  32. return updateTime;
  33. }
  34. public void setUpdateTime(Long updateTime) {
  35. this.updateTime = updateTime;
  36. }
  37.  
  38. public String getCreateBy() {
  39. return createBy;
  40. }
  41. public void setCreateBy(String createBy) {
  42. this.createBy = createBy;
  43. }
  44. public String getLastmodifiedBy() {
  45. return lastmodifiedBy;
  46. }
  47. public void setLastmodifiedBy(String lastmodifiedBy) {
  48. this.lastmodifiedBy = lastmodifiedBy;
  49. }
  50. }

@MappedSuperclass注解:

作用于实体类的父类上,父类不生成对应的数据库表

标注@MappedSuperclass的类不能再标注@Entity或@Table注解,也无需实现序列化接口

每个子类(实体类)对应一张数据库表,数据库表包含子类属性和父类属性

标注@MappedSuperclass的类可以直接标注@EntityListeners实体监听器

@EntityListeners(AuditingEntityListener.class)注解:

作用范围仅在标注@MappedSuperclass类的所有继承类中,并且实体监听器可以被其子类继承或重载

开启JPA的审计功能,需要在SpringBoot的入口类标注@EnableJpaAuditing

创建日期、修改日期有默认方法注入值,但创建人和修改人注入则需要手动实现AuditorAware接口:

  1. @Configuration
  2. public class BaseEntityAuditor implements AuditorAware<String> {
  3. @Override
  4. public Optional<String> getCurrentAuditor() {
  5. return "";
  6. }
  7. }

四、DAO层实现

JPA支持通过约定方法名进行数据库查询、修改:

  1. import org.springframework.data.jpa.repository.JpaRepository;
  2. import springbootjpa.entity.Article;
  3. public interface ArticleRepository extends JpaRepository<Article, Long> {
  4. Article findById(long id);
  5. }

通过约定方法名查询,只需实现JpaRepository接口声明查询方法而不需要具体实现

此外,可以在方法上标注@Query实现JPQL或原生SQL查询

JpaRepository<T, ID>,T表示要操作的实体对象,ID表示主键。该接口继承了分页排序接口PadingAndSortRepository,通过构建Pageable实现分页查询:

  1. @Autowired
  2. private ArticleRepository articleRepository;
  3. @RequestMapping("")
  4. public ModelAndView articlelist(@RequestParam(value = "start", defaultValue = "0") Integer start, @RequestParam(value = "limit", defaultValue = "5") Integer limit) {
  5. start = start < 0 ? 0 : start;
  6. Sort sort = Sort.by(Sort.Direction.DESC, "id");
  7. Pageable pageable = PageRequest.of(start, limit, sort);
  8. Page<Article> page = articleRepository.findAll(pageable);
  9. ModelAndView modelAndView = new ModelAndView("article/list");
  10. modelAndView.addObject("page", page);
  11. return modelAndView;
  12. }

如果根据某一字段排序,可以用Sort.by方法构建Sort对象;如果根据多个字段排序,首先构建Sort.Order数组List<Sort.Order>,然后再传入Sort.by方法构建Sort对象。

PageRequest.of方法生成Pageable对象

五、Contrller 控制器

  1. import org.springframework.beans.factory.annotation.Autowired;
  2. import org.springframework.data.domain.Page;
  3. import org.springframework.data.domain.PageRequest;
  4. import org.springframework.data.domain.Pageable;
  5. import org.springframework.data.domain.Sort;
  6. import org.springframework.stereotype.Controller;
  7. import org.springframework.web.bind.annotation.*;
  8. import org.springframework.web.servlet.ModelAndView;
  9. import springbootjpa.entity.Article;
  10. import springbootjpa.repository.ArticleRepository;
  11. @Controller
  12. @RequestMapping("/article")
  13. public class ArticleController {
  14. @Autowired
  15. private ArticleRepository articleRepository;
  16. @RequestMapping("")
  17. public ModelAndView articlelist(@RequestParam(value = "start", defaultValue = "0") Integer start,
  18. @RequestParam(value = "limit", defaultValue = "5") Integer limit) {
  19. start = start < 0 ? 0 : start;
  20. Sort sort = Sort.by(Sort.Direction.DESC, "id");
  21. Pageable pageable = PageRequest.of(start, limit, sort);
  22. Page<Article> page = articleRepository.findAll(pageable);
  23. ModelAndView modelAndView = new ModelAndView("article/list");
  24. modelAndView.addObject("page", page);
  25. return modelAndView;
  26. }
  27. @RequestMapping("/add")
  28. public String addArticle() {
  29. return "article/add";
  30. }
  31. @PostMapping("")
  32. public String saveArticle(Article article) {
  33. articleRepository.save(article);
  34. return "redirect:/article";
  35. }
  36. @GetMapping("/{id}")
  37. public ModelAndView getArticle(@PathVariable("id") Integer id) {
  38. Article article = articleRepository.findById(id);
  39. ModelAndView modelAndView = new ModelAndView("article/show");
  40. modelAndView.addObject("article", article);
  41. return modelAndView;
  42. }
  43. @DeleteMapping("/{id}")
  44. public String deleteArticle(@PathVariable("id") long id) {
  45. System.out.println("put 方法");
  46. articleRepository.deleteById(id);
  47. return "redirect:/article";
  48. }
  49. @GetMapping("edit/{id}")
  50. public ModelAndView editArticle(@PathVariable("id") Integer id) {
  51. Article article = articleRepository.findById(id);
  52. ModelAndView modelAndView = new ModelAndView("article/edit");
  53. modelAndView.addObject("article", article);
  54. return modelAndView;
  55. }
  56. @PutMapping("/{id}")
  57. public String editArticleSave(Article article, long id) {
  58. System.out.println("put 方法");
  59. article.setId(id);
  60. articleRepository.save(article);
  61. return "redirect:/article";
  62. }
  63. }

因为<form>表单只能发送GET或POST请求,spring3引入一个监听器HiddenHttpMethodFilter来将POST请求转换为PUT或POST请求。

SpringBoot2.x开始默认不自动注入HiddenHttpMethodFilter,需要设置spring.mvc.hiddenmethod.filter.enabled=true开启PUT、DELETE方法支持

配置完后,前端页面需要在表单中加入隐藏域,表明实际请求方法:

  1. <!-- DELETE 请求 -->
  2. <form id="deletePost" method="POST" action="">
  3. <input type="hidden" name="_method" value="delete">
  4. </form>
  5. <!-- PUT 请求 -->
  6. <form id="putPost" method="POST" action="">
  7. <input type="hidden" name="_method" value="put">
  8. </form>

六、其他

th:value和th:field区别:

th:value解析成html,表现为:value="${th:value}"

th:field解析成html,表现为:name="${th:name}" value="${th:value}"

以上为个人经验,希望能给大家一个参考,也希望大家多多支持我们。如有错误或未考虑完全的地方,望不吝赐教。

原文链接:https://blog.csdn.net/qq_14926283/article/details/110633636