我的预期输出是:
{
"message": " Invalid Booking Id ",
"statusCode": 400
}
我目前的回应是:
{
"type": "about:blank",
"title": "Internal Server Error",
"status": 500,
"detail": "Failed to write request",
"instance": "/hotel/booking/1/transaction"
}
这表明completePayment方法中发生了未处理的异常,并且通用错误处理程序正在捕获它,从而导致500内部服务器错误。
“InvalidPaymentException”问题是由于 Spring Boot 应用程序中未处理的异常而引起的。在提供的代码中,当付款模式不是“UPI”或“CARD”时,会引发“InvalidPaymentModeException”。但是,此异常并未按预期被捕获和处理。相反,会调用用于处理意外异常的通用异常处理程序,从而导致 500 内部服务器错误响应。
错误响应DTO
@NoArgsConstructor
@AllArgsConstructor
public class ErrorResponse {
private String message;
private int statusCode;
}
例外
public class InvalidBookingIdException extends RuntimeException {
public InvalidBookingIdException (String message){
super(message);
}
}
异常处理程序
@ControllerAdvice
public class CustomExceptionHandler extends ResponseEntityExceptionHandler {
private static final Logger log = LoggerFactory.getLogger(com.example.bookingservice.ExceptionHandler.CustomExceptionHandler.class);
@ExceptionHandler(InvalidPaymentModeException.class)
public ResponseEntity<com.example.bookingservice.dto.ErrorResponse> handleInvalidPaymentRequest(InvalidPaymentModeException ex, WebRequest request) {
log.error("InvalidPaymentModeException caught: " + ex.getMessage(), ex);
com.example.bookingservice.dto.ErrorResponse errorResponse = new com.example.bookingservice.dto.ErrorResponse(ex.getMessage(), HttpStatus.BAD_REQUEST.value());
return new ResponseEntity<>(errorResponse, HttpStatus.BAD_REQUEST);
}
}
控制器层
@RestController
@RequestMapping(value = "/hotel")
public class BookingController {
@Autowired
ModelMapper modelMapper;
@Autowired
BookingService bookingService;
@Autowired
RestTemplate restTemplate;
@PostMapping(value = "/booking/{id}/transaction", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<?> completePayment(@PathVariable(name = "id") int id, @RequestBody TransactionRequestDto transactionRequestDto) {
try{
// Retrieve the booking based on the provided ID
Booking requestedBooking = bookingService.getBookingBasedOnId(id);
// Ensure that the transactionRequestDto contains the necessary data
System.out.println("Payment Request: " + transactionRequestDto.toString());
// Check if the payment mode is valid
String paymentMode = transactionRequestDto.getPaymentMode();
if (!bookingService.isValidPaymentMode(paymentMode)) {
throw new InvalidPaymentModeException("Invalid mode of payment");
}
// Define the URL for the Payment Service
String transactionGet_IdUrl = "http://localhost:8082/payment/transaction";
// Make the POST request to the Payment Service
ResponseEntity<Integer> transactionResponse = restTemplate.postForEntity(transactionGet_IdUrl, transactionRequestDto, Integer.class);
if (transactionResponse.getStatusCode() == HttpStatus.CREATED) {
int transactionId = transactionResponse.getBody();
System.out.println("Transaction ID: " + transactionId);
// Update the booking with the transaction ID
requestedBooking.setTransactionId(transactionId);
bookingService.updateBooking(id, requestedBooking);
// Map the updated booking to a response DTO
BookingResponseDto bookingResponseDto = modelMapper.map(requestedBooking, BookingResponseDto.class);
return new ResponseEntity<>(bookingResponseDto, HttpStatus.CREATED);
} else {
// Handle the case where the payment transaction was not successful
return ResponseEntity.status(transactionResponse.getStatusCode()).build();
}
} catch (Exception e){
com.example.bookingservice.dto.ErrorResponse errorResponseForOtherExceptions = new com.example.bookingservice.dto.ErrorResponse("Internal Server Error", HttpStatus.INTERNAL_SERVER_ERROR.value());
return new ResponseEntity(errorResponseForOtherExceptions,HttpStatus.INTERNAL_SERVER_ERROR);
}
}
}
控制台
Hibernate: insert into booking (aadhar_number,booked_on,from_date,num_of_rooms,room_numbers,room_price,to_date,transaction_id,booking_id) values (?,?,?,?,?,?,?,?,?)
In CrudRepository ,exiting save
In BookingServiceImpls ,exiting createBooking
In BookingController ,exiting createBooking
In BookingController ,entering completePayment
In BookingServiceImpls ,entering getBookingBasedOnId
In CrudRepository ,entering findById
Hibernate: select b1_0.booking_id,b1_0.aadhar_number,b1_0.booked_on,b1_0.from_date,b1_0.num_of_rooms,b1_0.room_numbers,b1_0.room_price,b1_0.to_date,b1_0.transaction_id from booking b1_0 where b1_0.booking_id=?
In CrudRepository ,exiting findById
In BookingServiceImpls ,exiting getBookingBasedOnId
Payment Request: TransactionRequestDto(paymentMode=other, bookingId=3, upiId=upi details, cardNumber=65757668687)
In BookingServiceImpls ,entering isValidPaymentMode
In BookingServiceImpls ,exiting isValidPaymentMode
In BookingController ,exiting completePayment
这是因为你的 try/catch 块,
InvalidPaymentModeException
永远不会从你的方法中抛出。
实际上,你有这个:
try {
throw new InvalidPaymentModeException();
} catch (Exception e) {
com.example.bookingservice.dto.ErrorResponse errorResponseForOtherExceptions = new com.example.bookingservice.dto.ErrorResponse("Internal Server Error", HttpStatus.INTERNAL_SERVER_ERROR.value());
return new ResponseEntity(errorResponseForOtherExceptions,HttpStatus.INTERNAL_SERVER_ERROR);
}
因此,您抛出的异常将被捕获,并且永远不会从此方法中抛出。这就是为什么你的建议没有被触发,相反,你得到了
return new ResponseEntity(errorResponseForOtherExceptions,HttpStatus.INTERNAL_SERVER_ERROR);
的输出