实施用于 RESTful 服务的验证

验证是所有服务中的常见需求。我们将讨论 Java 验证 API,以在我们的 bean 文件中添加验证。当我们收到创建用户的请求时,我们应该验证其内容。如果无效,我们应该返回适当的响应。

让我们看看如何验证请求。

步骤 1: 打开 UserResource.java 文件。

步骤 2: 添加 @Valid 注释。这是 Javax 验证 API。其默认类路径是 spring-boot-starter-web。

UserResource.java

package cn.javatiku.server.main.user;  
import java.net.URI;  
import java.util.List;  
import javax.validation.Valid;  
import org.springframework.beans.factory.annotation.Autowired;  
import org.springframework.http.ResponseEntity;  
import org.springframework.web.bind.annotation.DeleteMapping;  
import org.springframework.web.bind.annotation.GetMapping;  
import org.springframework.web.bind.annotation.PathVariable;  
import org.springframework.web.bind.annotation.PostMapping;  
import org.springframework.web.bind.annotation.RequestBody;  
import org.springframework.web.bind.annotation.RestController;  
import org.springframework.web.servlet.support.ServletUriComponentsBuilder;  
@RestController  
public class UserResource   
{  
@Autowired  
private UserDaoService service;  
@GetMapping("/users")  
public List<User> retriveAllUsers()  
{  
return service.findAll();  
}  
//retrieves a specific user detail  
@GetMapping("/users/{id}")  
public User retriveUser(@PathVariable int id)  
{  
User user= service.findOne(id);  
if(user==null)  
//runtime exception  
throw new UserNotFoundException("id: "+ id);  
return user;  
}  
//method that delete a user resource  
@DeleteMapping("/users/{id}")  
public void deleteUser(@PathVariable int id)  
{  
User user= service.deleteById(id);  
if(user==null)  
//runtime exception  
throw new UserNotFoundException("id: "+ id);  
}  
//method that posts a new user detail and returns the status of the user resource  
@PostMapping("/users")  
public ResponseEntity<Object> createUser(@Valid @RequestBody User user)     
{  
User sevedUser=service.save(user);    
URI location=ServletUriComponentsBuilder.fromCurrentRequest().path("/{id}").buildAndExpand(sevedUser.getId()).toUri();  
return ResponseEntity.created(location).build();  
}  
}  

现在我们将在 User 类中的 namedate of birth 上添加验证。假设名称至少应有五个字符,出生日期应该在过去而不是现在。

步骤 3: 打开 User.java 文件。

步骤 4:name 变量上方添加 @Size(min=5) 注释。

步骤 5:dob 变量上方添加 @Past 注释。

User.java

package cn.javatiku.server.main.user;  
import java.util.Date;  
import javax.validation.constraints.Past;  
import javax.validation.constraints.Size;  
public class User   
{  
private Integer id;  
@Size(min=5)  
private String name;  
@Past  
private Date dob;  
//default constructor     
protected User()  
{  
      
}  
public User(Integer id, String name, Date dob)   
{  
super();  
this.id = id;  
this.name = name;  
this.dob = dob;  
}  
public Integer getId()   
{  
return id;  
}  
public void setId(Integer id)   
{  
this.id = id;  
}  
public String getName()   
{  
return name;  
}  
public void setName(String name)   
{  
this.name = name;  
}  
public Date getDob()   
{  
return dob;  
}  
public void setDob(Date dob)   
{  
this.dob = dob;  
}  
@Override  
public String toString()   
{  
//return "User [id=" + id + ", name=" + name + ", dob=" + dob + "]";  
return String.format("User [id=%s, name=%s, dob=%s]", id, name, dob);  
}  
}  

步骤 5: 打开 Rest 客户端 Postman,发送一个具有新用户名称 Tony kPOST 请求。它返回 Status: 201 Created

restful-web-services-validations.png

现在我们发送另一个 POST 请求。但是名称应该少于五个字符。它返回 Status: 400 Bad Request

restful-web-services-validations2.png

当我们创建 RESTful 服务时,我们需要考虑消费者如何知道出了什么问题。为了解决这个问题,我们将添加一个方法 handleMethodArgumentNotValid(),该方法在 ResponseEntityExceptionHandler 类中定义。这是当发生错误请求时触发的方法。

protected ResponseEntity<Object> handleMethodArgumentNotValid(  MethodArgumentNotValidException ex, HttpHeaders headers, HttpStatus status, WebRequest request)   
{  
return handleExceptionInternal(ex, null, headers, status, request);  
}  

步骤 6: 将上述方法复制并粘贴到 CustomizedResponseEntityExceptionHandler.java 文件中。

步骤 7: 添加注释 @Override,覆盖该方法。

CustomizedResponseEntityExceptionHandler.java

package cn.javatiku.server.main;  
import java.util.Date;  
import org.springframework.http.HttpHeaders;  
import org.springframework.http.HttpStatus;  
import org.springframework.http.ResponseEntity;  
import org.springframework.web.bind.MethodArgumentNotValidException;  
import org.springframework.web.bind.annotation.ControllerAdvice;  
import org.springframework.web.bind.annotation.ExceptionHandler;  
import org.springframework.web.bind.annotation.RestController;  
import org.springframework.web.context.request.WebRequest;  
import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler;  
import cn.javatiku.server.main.exception.ExceptionResponse;  
import cn.javatiku.server.main.user.UserNotFoundException;  
//defining exception handling for all the exceptions   
@ControllerAdvice  
@RestController  
public class CustomizedResponseEntityExceptionHandler extends ResponseEntityExceptionHandler  
{  
@ExceptionHandler(Exception.class)  
//override method of ResponseEntityExceptionHandler class  
public final ResponseEntity<Object> handleAllExceptions(Exception ex, WebRequest request)  
{  
//creating exception response structure  
ExceptionResponse exceptionResponse= new ExceptionResponse(new Date(), ex.getMessage(), request.getDescription(false));  
//returning exception structure and specific status   
return new ResponseEntity(exceptionResponse, HttpStatus.INTERNAL_SERVER_ERROR);  
}  
@ExceptionHandler(UserNotFoundException.class)  
//override method of ResponseEntityExceptionHandler class  
public final ResponseEntity<Object> handleUserNotFoundExceptions(UserNotFoundException ex, WebRequest request)  
{  
//creating exception response structure  
ExceptionResponse exceptionResponse= new ExceptionResponse(new Date(), ex.getMessage(), request.getDescription(false));  
//returning exception structure and specific status   
return new ResponseEntity(exceptionResponse, HttpStatus.NOT_FOUND);  
}  
@Override  
protected ResponseEntity<Object> handleMethodArgumentNotValid(MethodArgumentNotValidException ex, HttpHeaders headers, HttpStatus status, WebRequest request)   
{  
ExceptionResponse exceptionResponse= new ExceptionResponse(new Date(), ex.getMessage(), ex.getBindingResult().toString());  
//returning exception structure and specific status   
return new ResponseEntity(exceptionResponse, HttpStatus.BAD_REQUEST);  
}  
}  

步骤 8: 现在,我们通过 Postman 发送 POST 请求。它返回带有消息 Validation failed for argument 和其他详细信息的异常结构。

restful-web-services-validations3.png

用户很难理解这个消息。因此,我们现在将自定义消息更改为字符串 Validation Failed,而不是获取消息。

@Override  
protected ResponseEntity<Object> handleMethodArgumentNotValid(MethodArgumentNotValidException ex, HttpHeaders headers, HttpStatus status, WebRequest request)   
{  
ExceptionResponse exceptionResponse= new ExceptionResponse(new Date(), "Validation Failed", ex.getBindingResult().toString());  
//returning exception structure and specific status   
return new ResponseEntity(exceptionResponse, HttpStatus.BAD_REQUEST);  
}  

步骤 9: 再次发送 POST 请求。它返回我们自定义的更具体的异常消息。

restful-web-services-validations4.png

这可能对消费者有用。现在,我们再次自定义异常,使其更加错误特定。

步骤 10: 打开 User.java 文件,在 @Size 注释中添加属性 message="Name should have at least 5 characters"

@Size(min=5, message="Name should have at least 5 characters")

步骤 11: 再次,发送 POST 请求。它返回我们指定的更具体异常。

restful-web-services-validations5.png

我们还可以通过遵循 BindingResult 接口来进一步自定义异常。验证类别有多种异常消息。在 validation-api-2.0.1.Final.jar 中定义了以下验证类别。

restful-web-services-validations6.png

标签: spring, Spring教程, Spring语言学习, Spring框架, Spring框架教程, Spring框架高级教程, spring boot, spring boot入门教程, spring boot学习教程, spring boot下载, spring boot框架入门, spring boot面试题, spring boot笔试题, spring boot学习指南, spring boot技术