错误验证消息格式 Spring boot

Posted

技术标签:

【中文标题】错误验证消息格式 Spring boot【英文标题】:Error validation message format Spring boot 【发布时间】:2017-12-28 00:37:41 【问题描述】:

我是使用 Java 和 Spring boot 的新手,我正在尝试验证将存储在 DB 中的 json 输入,验证做得很好,问题是响应格式,我认为它对于 Angular 的客户端不可读JS,需要知道如何从这里更改输出格式:


"error": 
    "code": 400,
    "message": "Validation failed for classes [com.company.customerhelpcenter.domain.Ticket] during persist time for groups [javax.validation.groups.Default, ]\nList of constraint violations:[\n\tConstraintViolationImplinterpolatedMessage='Descripción no puede ser null', propertyPath=description, rootBeanClass=class com.company.customerhelpcenter.domain.Ticket, messageTemplate='Descripción no puede ser null'\n\tConstraintViolationImplinterpolatedMessage='not a well-formed email address', propertyPath=email, rootBeanClass=class com.company.customerhelpcenter.domain.Ticket, messageTemplate='org.hibernate.validator.constraints.Email.message'\n\tConstraintViolationImplinterpolatedMessage='Número de teléfono no puede ser null', propertyPath=phone, rootBeanClass=class com.company.customerhelpcenter.domain.Ticket, messageTemplate='Número de teléfono no puede ser null'\n]"

到这里


"error": 
    "description" : "Description cannot be null",
    "email": "Email cannot be null",
    "phone": "Phone cannot be null"
 

这是我的控制器

@PostMapping
public ResponseEntity<?> create(@RequestBody Ticket ticket)

    return new ResponseEntity<>(this.ticketService.create(ticket), HttpStatus.CREATED);

服务:

public Ticket create(Ticket ticket)

    return this.ticketRepository.save(ticket);

存储库:

@Repository
public interface TicketRepository extends JpaRepository<Ticket, Integer>, Serializable

实体

@Entity
@Table(name = "ticket")
public class Ticket implements Serializable

    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Basic(optional = false)
    @Column(name = "id")
    private Integer id;

    @Basic(optional = false)
    @NotNull(message = "Descripción no puede ser null")
    @Size(min = 1, max = 255)
    @Column(name = "description")
    private String description;

    @Basic(optional = false)
    @NotNull(message = "Número de teléfono no puede ser null")
    @Size(min = 1, max = 20)
    @Column(name = "phone")
    private String phone;

    @Basic(optional = false)
    @NotNull(message = "Email no puede ser null")
    @Size(min = 1, max = 80)
    @Email
    @Column(name = "email")
    private String email;

    @Basic(optional = false)
    @NotNull
    @Column(name = "locked")
    private boolean locked;

    @JoinColumn(name = "ticket_type_id", referencedColumnName = "id")
    @ManyToOne(optional = false, fetch = FetchType.EAGER)
    @Exclude
    private TicketType ticketType;

    @OneToMany(mappedBy = "ticket")
    private Set<TicketHistory> ticketHistories = new HashSet<TicketHistory>();


    public Integer getId()
    
        return this.id;
    

    public String getDescription()
    
        return this.description;
    

    public String getPhone()
    
        return this.phone;
    

    public String getEmail()
    
        return this.email;
    

    public TicketType getTicketType()
    
        return this.ticketType;
    

    public boolean isLocked()
    
        return this.locked;
    

    public Set<TicketHistory> getTicketHistories()
    
        return this.ticketHistories;
    

【问题讨论】:

【参考方案1】:

您的异常是ConstraintValidationException,这意味着代码通过了Controller,但由于验证无法将数据保存到数据库中。我的建议是在此之前验证数据,在获取控制器之前验证数据。所以,会是这样的:

@ControllerAdvice
public class GlobalExceptionHandler 

    @ExceptionHandler(MethodArgumentNotValidException.class)
    public ResponseEntity<Map<String, Object>> yourExceptionHandler(MethodArgumentNotValidException e) 
        Map<String, Object> response = new HashMap<String, Object>();
        Map<String, String> errors = new HashMap<String, String>();

        BindingResult bindingResult = e.getBindingResult();
        List<FieldError> fieldErrors = bindingResult.getFieldErrors();
        for (FieldError fieldError : fieldErrors) 
            errors.put(fieldError.getField(), fieldError.getDefaultMessage());
        

        response.put("error", errors);
        return new ResponseEntity<Map<String, Object>>(response, HttpStatus.BAD_REQUEST);
    

你的控制器应该有这个@Valid注解:

@PostMapping
public ResponseEntity<?> create(@RequestBody @Valid Ticket ticket) 
    return new ResponseEntity<>(this.ticketService.create(ticket), HttpStatus.CREATED);

然后,您在 Ticket 上的验证(如 @NotNull@Size 等)将被验证。

但是,如果您不想像这样进行验证并且只想处理ConstraintValidationException,您可以这样做:

@ControllerAdvice
public class GlobalExceptionHandler 

    @ExceptionHandler( ConstraintViolationException.class)
    public ResponseEntity<Map<String, Object>> yourExceptionHandler(ConstraintViolationException e) 
        Map<String, Object> response = new HashMap<String, Object>();
        Map<String, String> errors = new HashMap<String, String>();
        Set<ConstraintViolation<?>> constraintViolations = e.getConstraintViolations();

        for (ConstraintViolation<?> constraintViolation : constraintViolations) 
            errors.put(constraintViolation.getPropertyPath().toString() , constraintViolation.getMessage());
        

        response.put("error", errors);
        return new ResponseEntity<Map<String, Object>>(response, HttpStatus.BAD_REQUEST);
    

【讨论】:

以上是关于错误验证消息格式 Spring boot的主要内容,如果未能解决你的问题,请参考以下文章

在 Spring Security 中处理基本身份验证的未经授权的错误消息

Spring:如何解决验证错误->错误代码->错误消息

响应中未显示 Spring Boot 验证错误消息

Spring Security - 身份验证失败 - 空白消息

如何在 Spring 中使用从属性文件获取的错误消息的注释验证?

Spring Boot如何返回我自己的验证约束错误信息