我试图运行 Spring Boot 应用程序来添加 Ornament,并且尝试使用 Insomnia 上的 REST API 来测试错误以获得响应,例如将错误的验证(如整数变量中的字符串输入)放在一起,但它无法显示 500 Internal发生服务器错误。我尽了一切努力,但到目前为止还无法解决这个问题。谁能帮我解决这个问题吗?谢谢
package com.example.demo.controller;
import java.util.Random;
import java.util.stream.Collectors;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import com.example.demo.model.Ornament;
import com.example.demo.services.OrnamentService;
import jakarta.validation.Valid;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
@RestController
public class OrnamentController {
@Autowired
private OrnamentService ornamentService;
public OrnamentController(OrnamentService ornamentService) {
this.ornamentService = ornamentService;
}
@GetMapping("/listAllOrnaments")
public Flux<Ornament> listAllOrnaments() {
Flux<Ornament> randomOrnaments = Flux.fromStream(
new Random()
.ints(10)
.mapToObj(i -> generateRandomOrnament())
);
return randomOrnaments;
}
private Ornament generateRandomOrnament() {
Random random = new Random();
String name = "Ornament " + random.nextInt(1000);
double priceMin = ornamentService.getRandomPrice();
double priceMax = priceMin + random.nextDouble() * 100;
double priceMedian = (priceMin + priceMax) / 2;
return new Ornament(name, 0, 0, priceMin, priceMax, priceMedian, "");
}
@PostMapping("/addOrnament")
public Mono<ResponseEntity<String>> addOrnament(@Valid @RequestBody Ornament ornament, BindingResult bindingResult) {
if (bindingResult.hasErrors()) {
String errorMessage = bindingResult.getFieldErrors().stream()
.map(error -> {
String fieldName = error.getField();
String errorMsg = error.getDefaultMessage();
if (fieldName.equals("price") && errorMsg.contains("NumberFormatException")) {
return "Price should be a number.";
}
return "Validation error: Field '" + fieldName + "' " + errorMsg;
})
.collect(Collectors.joining(", "));
return Mono.just(ResponseEntity.badRequest().body("Validation error: " + errorMessage));
}
return ornamentService.addOrnament(ornament)
.thenReturn(ResponseEntity.ok("Ornament added successfully"))
.onErrorResume(ex -> Mono.just(ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(ex.getMessage())));
}
@GetMapping("/error")
public ResponseEntity<String> handleErrors() {
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("An error occurred.");
}
}
装饰控制器
package com.example.demo.exception;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException;
@ControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(S3ServiceException.class)
public ResponseEntity<String> handleS3ServiceException(S3ServiceException ex) {
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(ex.getMessage());
}
@ExceptionHandler(MethodArgumentTypeMismatchException.class)
public ResponseEntity<String> handleTypeMismatch(MethodArgumentTypeMismatchException ex) {
String errorMessage;
switch (ex.getName()) {
case "weight":
case "diamondCarat":
case "priceMin":
case "priceMax":
case "priceMedian":
errorMessage = "Validation error: Field '" + ex.getName() + "' should be a number.";
break;
default:
errorMessage = "Validation error: Field '" + ex.getName() + "' has invalid type.";
}
return ResponseEntity.badRequest().body(errorMessage);
}
@ExceptionHandler(Exception.class)
public ResponseEntity<String> handleException(Exception ex) {
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("Internal server error occurred.");
}
}
全局异常处理程序
package com.example.demo.model;
import jakarta.validation.constraints.Max;
import jakarta.validation.constraints.Min;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import reactor.core.publisher.Mono;
@Data
public class Ornament {
@NotNull
private String name;
@Min(0)
private double weight;
@Min(0)
private double diamondCarat;
@Min(0)
private double priceMin;
@Max(10)
private double priceMax;
@Min(0)
private double priceMedian;
private String currency;
public Ornament(String name, double weight, double diamondCarat, double priceMin, double priceMax, double priceMedian, String currency) {
this.name = name;
this.weight = weight;
this.diamondCarat = diamondCarat;
this.priceMin = priceMin;
this.priceMax = priceMax;
this.priceMedian = priceMedian;
this.currency = currency;
}
public Mono<Ornament> toMono() {
return Mono.just(this);
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getWeight() {
return weight;
}
public void setWeight(double weight) {
this.weight = weight;
}
public double getDiamondCarat() {
return diamondCarat;
}
public void setDiamondCarat(double diamondCarat) {
this.diamondCarat = diamondCarat;
}
public double getPriceMin() {
return priceMin;
}
public void setPriceMin(double priceMin) {
this.priceMin = priceMin;
}
public double getPriceMax() {
return priceMax;
}
public void setPriceMax(double priceMax) {
this.priceMax = priceMax;
}
public double getPriceMedian() {
return priceMedian;
}
public void setPriceMedian(double priceMedian) {
this.priceMedian = priceMedian;
}
public String getCurrency() {
return currency;
}
public void setCurrency(String currency) {
this.currency = currency;
}
}
装饰品
package com.example.demo.services;
import java.util.Random;
import org.springframework.stereotype.Service;
import com.example.demo.model.Ornament;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
@Service
public class OrnamentService {
private final Random random = new Random();
public Flux<Ornament> listAllOrnaments() {
return Flux.just(new Ornament("Ornament 1", 0, 0, 0, 0, 0, ""),
new Ornament("Ornament 2", 0, 0, 0, 0, 0, ""),
new Ornament("Ornament 3", 0, 0, 0, 0, 0, ""));
}
public Mono<Ornament> addOrnament(Ornament ornament) {
return Mono.just(ornament);
}
public double getRandomPrice() {
return 1 + (100 - 1) * random.nextDouble();
}
}
饰品服务
{
"name": "Ornament 100",
"weight": "twenty",
"diamondCarat": 10,
"priceMin": 20,
"priceMax": 10,
"priceMedian": 20,
"currency": null
}
REST API JSON 测试
如果您打算从您的
@ControllerAdvice
转发验证错误,请尝试
覆盖下面共享的 handleMethodArgumentNotValid
的实现。自过去以来,当我们尝试类似的事情时,这对我们来说一直有效:
@Override // instead of @ExceptionHandler(MethodArgumentNotValidException.class), to avoid ambiguity from parent
protected ResponseEntity<Object> handleMethodArgumentNotValid(
MethodArgumentNotValidException ex, HttpHeaders headers, HttpStatusCode status, WebRequest request) {
String errorMessage;
switch (ex.getName()) {
case "weight":
case "diamondCarat":
case "priceMin":
case "priceMax":
case "priceMedian":
errorMessage = "Validation error: Field '" + ex.getName() + "' should be a number.";
break;
default:
errorMessage = "Validation error: Field '" + ex.getName() + "' has invalid type.";
}
return ResponseEntity.badRequest().body(errorMessage);
}