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约定创建包,如下所示。
使用生成的代码,我们在根包中获得一个类,即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