1.简介

一段时间以来,Spring框架已成为事实上的标准,可以创建任何基于REST API的应用程序。 Spring提供了各种现成的组件,以避免编写重复而繁琐的样板代码。 另外,关于Spring的美丽之处在于,如果有现成的解决方案,它就可以解决。 它为您提供了与现有库/框架集成的简便方法。 在本文中,让我们看看如何使用全栈Spring技术编写基于Spring的RESTful API。 Spring Boot,Spring Validations和Spring数据JPA的示例显示了以下方面的完整信息:

  • Spring Boot及其配置
  • 使用Spring Boot Starters进行依赖管理
  • 使用Spring数据JPA避免瓶颈DAO代码。
  • Spring支持VO级别的验证。
  • 集中式异常处理。

我们使用Gradle进行依赖管理并作为构建工具。 让我们逐步进行。

2.生成项目

这是生成项目所需遵循的步骤。

2.1 Spring Intializer

Spring在此位置Spring INITIALIZR提供了易于启动的项目生成工具。 在此网页上,您可以通过添加所需的依赖项来引导应用程序。 您可以通过添加下面提到的3个依赖项来生成项目框架(请参见下图以清楚了解)。
1.'Web':此依赖关系是编码Web层和创建API所必需的。 生成项目后,它在build.gralde文件中显示为以下依赖项。
compile('org.springframework.boot:spring-boot-starter-web') 2.'Validation':启用弹簧验证。 它在build.gradle中显示为以下依赖项。 compile('org.springframework.boot:spring-boot-starter-validation') 3.'JPA':启用弹簧数据JPA。 它在build.gradle中显示为以下依赖项。 compile('org.springframework.boot:spring-boot-starter-data-jpa')

弹簧初始化器

2.2 Eclipse配置

生成项目并将其导入到Eclipse中。 完成此操作后,就可以创建API。 在eclipse中导入的项目应如下所示。

项目结构

3.创建API

在编写API之前,让我们根据Java约定创建包,如下所示。

Java包

使用生成的代码,我们在根包中获得一个类,即com.example.spring.springrestapp。 这是我们的启动类。

入门班

注意:应该使用默认配置在根软件包级别创建启动类。
现在,让我们继续创建控制器类和API方法,以向数据库添加用户详细信息。 对于我们将要构建的该API,让我们假设一些约束作为我们的要求:

  • 该API应该收集用户的名字,姓氏,电子邮件,地址和电话号码并将其存储在MySQL DB中
  • API调用者将姓,名和电子邮件作为必填字段传递。 电子邮件应经过格式验证。
  • 家庭住址和电话号码可以是可选的。

4.配置数据库详细信息:

对于此项目,您需要运行MySQL DB的本地实例。 您可以在application.properties中提供数据库详细信息,如下所示。

应用特性

spring.datasource.url = jdbc:mysql://localhost:3306/boot_app
spring.datasource.username = root
spring.datasource.password = root

在MySQL DB中,使用以下脚本在MySQL DB中创建一个包含名字,姓氏,电子邮件,地址和电话号码的表。

创建表脚本

create table user_info(
user_id smallint(10) primary key auto_increment,
first_name varchar(150),
last_name varchar(150),
email varchar(200),
address varchar(250),
phone smallint(10)
);

5.配置Spring Data JPA

表准备好后,我们需要使用JPA将其映射为Java对象。 该表的每个字段都使用注释映射到java对象中。 以下是我们实体的外观。

JPA实体

package com.example.spring.springrestapp.dao.entity;import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Table;
import javax.validation.constraints.Email;
import javax.validation.constraints.NotBlank;import org.springframework.data.annotation.Id;@Entity
@Table(name = "user_info")
public class UserInformation {@Id@GeneratedValue(strategy = GenerationType.IDENTITY)@Column(name = "USER_ID")private Integer userId;@Column(name = "FIRST_NAME")private String firstName;@Column(name = "LAST_NAME")private String lastName;@Column(name = "EMAIL")private String email;@Column(name = "ADDRESS")private String address;@Column(name = "PHONE")private Integer phone;public String getFirstName() {return firstName;}public void setFirstName(String firstName) {this.firstName = firstName;}public String getLastName() {return lastName;}public void setLastName(String lastName) {this.lastName = lastName;}public String getAddress() {return address;}public void setAddress(String address) {this.address = address;}public Integer getPhone() {return phone;}public void setPhone(Integer phone) {this.phone = phone;}public String getEmail() {return email;}public void setEmail(String email) {this.email = email;}
}

现在,创建Spring数据JPA存储库。 可以通过如下扩展接口JpaRepository来创建数据JPA存储库。 (请注意,您需要传递ID字段的实体和数据类型。在我的示例中,entity是User,而id字段的类型是Integer)

JPA存放区

package com.example.spring.springrestapp.dao.repo;import org.springframework.data.jpa.repository.JpaRepository;
import com.example.spring.springrestapp.dao.entity.UserInformation;
public interface UserRepo extends JpaRepository {}

如此简单,我们的DAO代码已准备就绪! Spring负责生成基础的DAO实现。

6.服务和控制器层

现在,我们创建一个服务类来保存用户详细信息。 您可以根据需要在方法中添加业务逻辑。

服务等级

@Service
public class UserDetailService {@Autowiredprivate UserRepo userRepo;public UserInformation saveUser(UserInformation user) {return userRepo.save(user);}
}

现在让我们创建一个控制器和API方法。 saveUser api在请求正文中接受json数据,然后在正文中以JSON形式返回响应。

控制器层

@RestController
@RequestMapping("/api/user")
public class SpringRestAppController {@Autowiredprivate UserDetailService userService;@PostMapping(value = "/save")public @ResponseBody UserInformation createUser(@RequestBody UserInformation user) {return userService.saveUser(user);}
}

@RequestMapping用于映射资源。
@PostMapping与分配给@RequestMapping HttpPost相同。

7.配置VO级别验证

我们的API需要按照开头提到的要求对其收到的数据进行验证。 为此,我们将在实体级别应用数据验证,如下所示。

数据验证

@Entity
@Table(name = "user_info")
public class UserInformation {@Id@GeneratedValue(strategy = GenerationType.IDENTITY)@Column(name = "USER_ID")private Integer userId;@Column(name = "FIRST_NAME")@NotBlank(message = "first name can't be blank")private String firstName;@Column(name = "LAST_NAME")@NotBlank(message = "last name can't be blank")private String lastName;@Column(name = "EMAIL")@NotBlank(message = "email can't be blank")@Email(message = "invalid format")private String email;@Column(name = "ADDRESS")private String address;@Column(name = "PHONE")private Integer phone;

请注意,注释@NotBlank不允许为空或null值, @Email不能检查有效的电子邮件格式。 此外,我们添加了验证失败的消息。

现在,我们需要告诉Spring按照实体中指定的注释进行验证。 为此,我们可以在请求有效负载上使用@Valid注释,如下所示。

@PostMapping(value = "/save")public @ResponseBody User createUser(@RequestBody @Valid UserInformation user) {return userService.saveUser(user);}

8.配置异常处理

验证失败时,我们需要将正确格式的错误响应提供给API使用方。 例如,如果没有给出名字,我想以以下格式返回错误消息,并带有HTTP错误代码错误请求。 为API使用者提供异常堆栈跟踪不是一个好主意。

{
"errorCode": "VALIDATION_FAILED",
"message": ""
}

我们可以在每个API控制器方法中执行此操作,也可以创建单个全局异常处理,从而避免出于相同需求在多个位置编写重复代码。
为了在一个地方处理中央异常,我们利用了Spring的错误处理程序。 在Spring 3.2中,提供了@ControllerAdvice以全球化异常/错误处理。 要返回错误响应,请创建一个具有错误代码和消息的VO。

值对象中的错误处理

@JsonInclude(content = Include.NON_NULL)
@JsonIgnoreProperties(ignoreUnknown = true)
public class ApiErrorVO {private String errorCode;private String message;public ApiErrorVO(String errorCode, String message) {super();this.errorCode = errorCode;this.message = message;}

当验证失败时,Spring会抛出MethodArgumentNotValidException 。 我们可以捕获此异常并从抛出的异常中提取错误消息。 我们使用@ExceptionHandler捕获异常,如下所示。

异常处理

@ControllerAdvice
public class ApiExceptionHandler {@ExceptionHandler(MethodArgumentNotValidException.class)@ResponseStatus(code = HttpStatus.BAD_REQUEST)@ResponseBodypublic ApiErrorVO handleValidationError(MethodArgumentNotValidException ex) {BindingResult bindingResult = ex.getBindingResult();FieldError fieldError = bindingResult.getFieldError();String defaultMessage = fieldError.getDefaultMessage();return new ApiErrorVO("VALIDATION_FAILED", defaultMessage);}
}

@ResponseStatus用于指定HTTP错误的请求状态。
@ResponseBody确保将错误写入响应正文。

9.结论

现在让我们测试一下API。

情况1:验证失败
网址: http://localhost:8080/restApp/api/user/save
RequestPayload:请注意空白的名字

{
"firstName":"",
"lastName":"K",
"email":"alexk@abc.com"
}

响应:HTTP状态为400

{
"errorCode": "VALIDATION_FAILED",
"message": "first name can't be blank"
}

情况2:提供所有必需值时
请求有效负载:

{
"firstName":"Alex",
"lastName":"K",
"email":"alexk@abc.com"
}

响应:HTTP状态为200

{
"userId": 8,
"firstName": "Alex",
"lastName": "K",
"email": "alexk@abc.com",
"address": null,
"phoneNumber": null
}

测试结束。

10.下载源代码

下载
您可以在此处下载完整的源代码: SPRING DATA JPA

翻译自: https://www.javacodegeeks.com/2018/08/spring-data-jpa-central-exception-handling-vo-validations-framework.html

具有中央异常处理和VO验证的Spring Data JPA –框架相关推荐

  1. 客户端soap【JAX-WS入门系列】第04章_SOAP异常处理和Handler处理

    这段时间一直在查找客户端soap之类的问题,下午恰好有机会和大家共享一下. 客户端和服务端都是Java Project,首先列出服务端代码 首先是SEI,即服务端接口类HelloService.jav ...

  2. java 运行异常处理_Java编程异常处理和I/O流

    重点: 1.在编写程序时,要正确地使用捕获例外和声明抛出异常的两种例外处理的方法. 2.遇到实际问题时,要根据需要正确使用各种输入/输出流,特别是对中文使用适当的字符输入流. 3.正确使用对象串行化的 ...

  3. Java第六次作业--异常处理和Java类集

    (一)学习总结 1.用思维导图对本周的学习内容进行总结. 2.当程序中出现异常时,JVM会依据方法调用顺序依次查找有关的错误处理程序.可使用printStackTrace 和getMessage方法了 ...

  4. 异常处理和UDP协议

    一.什么是异常? 程序在运行过程中出现了不可预知的错误,并且该错误没对应的处理机制,那么就会以异常的形式表示出来, 造成的影响就是整个程序无法再正常的运行,抛出异常. 二.异常的结构: 1:异常的类型 ...

  5. vb.net结构化异常处理和“邪用”

    vb.net中的错误处理包括两种:非结构化异常处理技术和结构化异常处理.非结构化异常处理技术在vb 6.0中使用的比较普遍,即通过Err对象和ON Error.Go To.Resume等语句来实现.这 ...

  6. oracle plsql异常,【Oracle篇】异常处理和PLSQL

    一.所有的PL/SQL异常都具有以下几个基本特征: 错误类型:表示了错误是ORA错误还是PLS错误 错误代号:一串表示错误代号的数字 错误文本:错误消息文本,包括错误代号 二.PL/SQL会产生两种类 ...

  7. Python3中异常处理和try/except,try/finally的用法

    1:Python3中异常处理介绍 在Python中当发生错误时,Python中的异常会自动触发,异常也能由代码触发和拦截,Python中有如下语句来触发,处理异常: a:try/except:拦截由P ...

  8. R语言中的异常处理和eval函数

    异常处理tryCatch() [R]R语言里的异常处理与错误控制 看看下面这个例子就能快速了解. #这里不要用c(1,2,'a',4), 因为R中向量中的元素必须一致,会自动转换成c("1& ...

  9. Spring Data JPA 从入门到精通~@PreUpdate异常场景分析

    1.执行save()后,再次save(),@PreUpdate不再触发 2.@Transient字段的变更,不会触发@PreUpdate方法 3.@PreUpdate 不适用加密/解密场景 1.执行s ...

最新文章

  1. 最近5年,诺贝尔化学奖都颁给了谁?
  2. Windows内核实验005 Inline Hook
  3. sublime配置python3_Sublime Text 3 Python3环境配置
  4. 有BUG!!!慎用default文本
  5. 进程的逻辑设备如何与一个物理设备建立对应的关系?
  6. 课时39.细线表格(理解)
  7. 基于Java+SpringBoot+vue+element实现前后端分离牙科诊所管理系统详细设计
  8. http://jingyan.baidu.com/article/2009576193ee38cb0721b416.html
  9. 北京大学数学科学学院2006/9/20声明:坚持真理、追求卓越zz
  10. 解决Visual Studio 2008 下,打开.dbml(LINQ) 文件时,提示The operation could not be completed. 的问题。...
  11. Shell Notes(2)
  12. 树莓派 之 动态DNS(DNSPod)
  13. Vue 下载文件需要token设置
  14. hadoop(二)-hadoop原理及架构
  15. 今天来说说白色white
  16. 安装vim管理插件 pathogen
  17. 尝试导出Cities Skyline完整城市模型遇到的问题与解决
  18. Devc++使用及debug超详解
  19. 蕾哈娜首个护肤品牌全球发售;凯悦首旅如家合资首批五家逸扉酒店揭幕 | 美通企业日报...
  20. SAP SMW0 上传EXCEL模板

热门文章

  1. 奶牛的交叉路(jzoj 1756)
  2. 【动态规划】最大子矩阵之和
  3. Nacos(七)之Spring Cloud集成
  4. 面试官:为什么 Spring Boot 的 jar 可以直接运行
  5. Java中随机数的原理,以及使用时的注意点
  6. 正则表达式真的很骚,可惜你不会写
  7. Oracle入门(十四.4)之在PL / SQL中使用变量
  8. 并发编程 – Concurrent 用户指南
  9. 分布式Session共享解决方案
  10. 2022的第一天,立个目标