具有中央异常处理和VO验证的Spring Data JPA –框架
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 –框架相关推荐
- 客户端soap【JAX-WS入门系列】第04章_SOAP异常处理和Handler处理
这段时间一直在查找客户端soap之类的问题,下午恰好有机会和大家共享一下. 客户端和服务端都是Java Project,首先列出服务端代码 首先是SEI,即服务端接口类HelloService.jav ...
- java 运行异常处理_Java编程异常处理和I/O流
重点: 1.在编写程序时,要正确地使用捕获例外和声明抛出异常的两种例外处理的方法. 2.遇到实际问题时,要根据需要正确使用各种输入/输出流,特别是对中文使用适当的字符输入流. 3.正确使用对象串行化的 ...
- Java第六次作业--异常处理和Java类集
(一)学习总结 1.用思维导图对本周的学习内容进行总结. 2.当程序中出现异常时,JVM会依据方法调用顺序依次查找有关的错误处理程序.可使用printStackTrace 和getMessage方法了 ...
- 异常处理和UDP协议
一.什么是异常? 程序在运行过程中出现了不可预知的错误,并且该错误没对应的处理机制,那么就会以异常的形式表示出来, 造成的影响就是整个程序无法再正常的运行,抛出异常. 二.异常的结构: 1:异常的类型 ...
- vb.net结构化异常处理和“邪用”
vb.net中的错误处理包括两种:非结构化异常处理技术和结构化异常处理.非结构化异常处理技术在vb 6.0中使用的比较普遍,即通过Err对象和ON Error.Go To.Resume等语句来实现.这 ...
- oracle plsql异常,【Oracle篇】异常处理和PLSQL
一.所有的PL/SQL异常都具有以下几个基本特征: 错误类型:表示了错误是ORA错误还是PLS错误 错误代号:一串表示错误代号的数字 错误文本:错误消息文本,包括错误代号 二.PL/SQL会产生两种类 ...
- Python3中异常处理和try/except,try/finally的用法
1:Python3中异常处理介绍 在Python中当发生错误时,Python中的异常会自动触发,异常也能由代码触发和拦截,Python中有如下语句来触发,处理异常: a:try/except:拦截由P ...
- R语言中的异常处理和eval函数
异常处理tryCatch() [R]R语言里的异常处理与错误控制 看看下面这个例子就能快速了解. #这里不要用c(1,2,'a',4), 因为R中向量中的元素必须一致,会自动转换成c("1& ...
- Spring Data JPA 从入门到精通~@PreUpdate异常场景分析
1.执行save()后,再次save(),@PreUpdate不再触发 2.@Transient字段的变更,不会触发@PreUpdate方法 3.@PreUpdate 不适用加密/解密场景 1.执行s ...
最新文章
- 最近5年,诺贝尔化学奖都颁给了谁?
- Windows内核实验005 Inline Hook
- sublime配置python3_Sublime Text 3 Python3环境配置
- 有BUG!!!慎用default文本
- 进程的逻辑设备如何与一个物理设备建立对应的关系?
- 课时39.细线表格(理解)
- 基于Java+SpringBoot+vue+element实现前后端分离牙科诊所管理系统详细设计
- http://jingyan.baidu.com/article/2009576193ee38cb0721b416.html
- 北京大学数学科学学院2006/9/20声明:坚持真理、追求卓越zz
- 解决Visual Studio 2008 下,打开.dbml(LINQ) 文件时,提示The operation could not be completed. 的问题。...
- Shell Notes(2)
- 树莓派 之 动态DNS(DNSPod)
- Vue 下载文件需要token设置
- hadoop(二)-hadoop原理及架构
- 今天来说说白色white
- 安装vim管理插件 pathogen
- 尝试导出Cities Skyline完整城市模型遇到的问题与解决
- Devc++使用及debug超详解
- 蕾哈娜首个护肤品牌全球发售;凯悦首旅如家合资首批五家逸扉酒店揭幕 | 美通企业日报...
- SAP SMW0 上传EXCEL模板