关于来自 REST 应用程序的异常的漂亮消息
Pretty message on exceptions from REST app
我的 REST 应用程序有问题。下面是gitlink减轻你的负担:https://github.com/TheNiceGuy123/AstonishingBackEnd
这里也是原始代码:
类 发布顺序:
员工控制器:
package com.example.csmartbackend.controller;
import com.example.csmartbackend.model.Employee;
import com.example.csmartbackend.modeldto.EmployeeDto;
import com.example.csmartbackend.service.EmployeeService;
import lombok.RequiredArgsConstructor;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import javax.validation.Valid;
import java.util.List;
import java.util.UUID;
@RestController
@RequestMapping("employee")
@RequiredArgsConstructor
public class EmployeeController
{
private final EmployeeService employeeService;
@GetMapping("find/{Cnp}")
public ResponseEntity<Employee> findByCNP(@PathVariable("Cnp") String Cnp)
{
Employee employee = employeeService.findByCnp(Cnp);
HttpHeaders header = new HttpHeaders();
header.add("Desc","Getting employee by id.");
return ResponseEntity.status(HttpStatus.OK).headers(header).body(employee);
}
}
员工服务:
package com.example.csmartbackend.service;
import com.example.csmartbackend.mapper.EmployeeMapper;
import com.example.csmartbackend.model.Employee;
import com.example.csmartbackend.modeldto.EmployeeDto;
import com.example.csmartbackend.repository.EmployeeRepository;
import exception.general.TargetNotFoundException;
import exception.requestsexceptions.CNPNotFoundException;
import exception.requestsexceptions.EmployeeNotFoundException;
import exception.requestsexceptions.InvalidIdException;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import javax.transaction.Transactional;
import java.util.List;
import java.util.Optional;
import java.util.UUID;
@Service
@RequiredArgsConstructor
@Transactional
public class EmployeeService implements EmployeeServiceImpl
{
private final EmployeeRepository employeeRepository;
private final ContractService contractService;
private final AdressService adressService;
public Employee findByCnp(String Cnp) throws CNPNotFoundException
{
Optional<Employee> employeeOptional = Optional.ofNullable(employeeRepository.findByCnp(Cnp));
if(employeeOptional.isPresent())
return employeeOptional.get();
else
throw new CNPNotFoundException("No employee found.");
}
}
全局异常处理程序:
package exception.requestsexceptions;
import org.springframework.beans.TypeMismatchException;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.web.HttpMediaTypeNotSupportedException;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MissingPathVariableException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.context.request.WebRequest;
import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
@ControllerAdvice
public class GlobalExceptionHandler extends ResponseEntityExceptionHandler
{
@Override
protected ResponseEntity<Object> handleHttpRequestMethodNotSupported
(HttpRequestMethodNotSupportedException ex, HttpHeaders headers, HttpStatus status, WebRequest request)
{
String message = ex.getMessage();
List<String> details = new ArrayList<>();
details.add("Request method not supported.");
ApiErrorModel apiErrorModel = new ApiErrorModel(message, details, status, LocalDateTime.now());
return ResponseEntity.status(status).body(apiErrorModel);
}
@Override
protected ResponseEntity<Object> handleHttpMediaTypeNotSupported
(HttpMediaTypeNotSupportedException ex, HttpHeaders headers, HttpStatus status, WebRequest request)
{
String message = ex.getMessage();
List<String> details = new ArrayList<>();
details.add("Media method not supported.");
ApiErrorModel apiErrorModel = new ApiErrorModel(message, details, status, LocalDateTime.now());
return ResponseEntity.status(status).body(apiErrorModel);
}
@Override
protected ResponseEntity<Object> handleMissingPathVariable
(MissingPathVariableException ex, HttpHeaders headers, HttpStatus status, WebRequest request)
{
String message = ex.getMessage();
List<String> details = new ArrayList<>();
details.add("Path variable is missing.");
ApiErrorModel apiErrorModel = new ApiErrorModel(message, details, status, LocalDateTime.now());
return ResponseEntity.status(status).body(apiErrorModel);
}
@Override
protected ResponseEntity<Object> handleMissingServletRequestParameter
(MissingServletRequestParameterException ex, HttpHeaders headers, HttpStatus status, WebRequest request)
{
String message = ex.getMessage();
List<String> details = new ArrayList<>();
details.add("Request parameter is missing.");
ApiErrorModel apiErrorModel = new ApiErrorModel(message, details, status, LocalDateTime.now());
return ResponseEntity.status(status).body(apiErrorModel);
}
@Override
protected ResponseEntity<Object> handleTypeMismatch
(TypeMismatchException ex, HttpHeaders headers, HttpStatus status, WebRequest request)
{
String message = ex.getMessage();
List<String> details = new ArrayList<>();
details.add("Mismatch of type.");
ApiErrorModel apiErrorModel = new ApiErrorModel(message, details, status, LocalDateTime.now());
return ResponseEntity.status(status).body(apiErrorModel);
}
@Override
protected ResponseEntity<Object> handleHttpMessageNotReadable
(HttpMessageNotReadableException ex, HttpHeaders headers, HttpStatus status, WebRequest request)
{
String message = ex.getMessage();
List<String> details = new ArrayList<>();
details.add("Request body is not readable.");
ApiErrorModel apiErrorModel = new ApiErrorModel(message, details, status, LocalDateTime.now());
return ResponseEntity.status(status).body(apiErrorModel);
}
@ExceptionHandler(EmployeeNotFoundException.class)
public ResponseEntity<Object> handleEmployeeNotFoundException(EmployeeNotFoundException ex)
{
String message = ex.getMessage();
List<String> details = new ArrayList<>();
details.add("Employee not found.");
ApiErrorModel apiErrorModel = new ApiErrorModel(message, details, HttpStatus.BAD_REQUEST, LocalDateTime.now());
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(apiErrorModel);
}
@ExceptionHandler(CNPNotFoundException.class)
public ResponseEntity<Object> handleInvalidCNPException(CNPNotFoundException ex)
{
String message = ex.getMessage();
List<String> details = new ArrayList<>();
details.add("Employee with the given CNP not found.");
ApiErrorModel apiErrorModel = new ApiErrorModel(message, details, HttpStatus.NOT_FOUND, LocalDateTime.now());
return ResponseEntity.status(HttpStatus.NOT_FOUND).body(apiErrorModel);
}
}
CNPNotFoundException class:
package exception.requestsexceptions;
public class CNPNotFoundException extends RuntimeException
{
public CNPNotFoundException(String message) { super(message); }
}
ApiErrorModel class:
package exception.requestsexceptions;
import lombok.*;
import org.springframework.http.HttpStatus;
import java.time.LocalDateTime;
import java.util.List;
@Setter
@Getter
@NoArgsConstructor
@AllArgsConstructor
@ToString
public class ApiErrorModel
{
String message;
List<String> details;
HttpStatus status;
LocalDateTime timestamp;
}
我想像第二张图片中那样向用户提供一些相关信息,但在邮递员中,一切都保持在默认级别以这样调用它,就像我的处理程序代码甚至不存在一样。我是否遗漏了任何逻辑或注释?
This is how it looks on my side
This is how it should look like
感谢您的宝贵时间!
问题是当 class 被注释为 @SpringBootApplication
而没有任何属性时 SpringBoot 仅扫描 class 本身所在的包及其子包。
在您的情况下,这意味着 Spring当您将 GlobalExceptionHandler
class 放入 [=13] 时,引导仅查找 com.example.csmartbackend
包下的任何 Spring 组件=]s包。
要修复它,您有两种选择:
- 将
exception
包放在 com.example.csmartbackend 下,所以它将是 com.example.csmartbackend.exception.requestsexception.GlobalExceptionHandler
- 告诉 spring 也扫描
exception
包,使用 scanBasePackageClasses
或 scanBasePackages
属性,例如 @SpringBootApplication(scanBasePackageClasses = {CSmartBackEndApplication.class, GlobalExceptionHandler.class})
我的 REST 应用程序有问题。下面是gitlink减轻你的负担:https://github.com/TheNiceGuy123/AstonishingBackEnd
这里也是原始代码:
类 发布顺序:
员工控制器:
package com.example.csmartbackend.controller;
import com.example.csmartbackend.model.Employee;
import com.example.csmartbackend.modeldto.EmployeeDto;
import com.example.csmartbackend.service.EmployeeService;
import lombok.RequiredArgsConstructor;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import javax.validation.Valid;
import java.util.List;
import java.util.UUID;
@RestController
@RequestMapping("employee")
@RequiredArgsConstructor
public class EmployeeController
{
private final EmployeeService employeeService;
@GetMapping("find/{Cnp}")
public ResponseEntity<Employee> findByCNP(@PathVariable("Cnp") String Cnp)
{
Employee employee = employeeService.findByCnp(Cnp);
HttpHeaders header = new HttpHeaders();
header.add("Desc","Getting employee by id.");
return ResponseEntity.status(HttpStatus.OK).headers(header).body(employee);
}
}
员工服务:
package com.example.csmartbackend.service;
import com.example.csmartbackend.mapper.EmployeeMapper;
import com.example.csmartbackend.model.Employee;
import com.example.csmartbackend.modeldto.EmployeeDto;
import com.example.csmartbackend.repository.EmployeeRepository;
import exception.general.TargetNotFoundException;
import exception.requestsexceptions.CNPNotFoundException;
import exception.requestsexceptions.EmployeeNotFoundException;
import exception.requestsexceptions.InvalidIdException;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import javax.transaction.Transactional;
import java.util.List;
import java.util.Optional;
import java.util.UUID;
@Service
@RequiredArgsConstructor
@Transactional
public class EmployeeService implements EmployeeServiceImpl
{
private final EmployeeRepository employeeRepository;
private final ContractService contractService;
private final AdressService adressService;
public Employee findByCnp(String Cnp) throws CNPNotFoundException
{
Optional<Employee> employeeOptional = Optional.ofNullable(employeeRepository.findByCnp(Cnp));
if(employeeOptional.isPresent())
return employeeOptional.get();
else
throw new CNPNotFoundException("No employee found.");
}
}
全局异常处理程序:
package exception.requestsexceptions;
import org.springframework.beans.TypeMismatchException;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.web.HttpMediaTypeNotSupportedException;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MissingPathVariableException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.context.request.WebRequest;
import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
@ControllerAdvice
public class GlobalExceptionHandler extends ResponseEntityExceptionHandler
{
@Override
protected ResponseEntity<Object> handleHttpRequestMethodNotSupported
(HttpRequestMethodNotSupportedException ex, HttpHeaders headers, HttpStatus status, WebRequest request)
{
String message = ex.getMessage();
List<String> details = new ArrayList<>();
details.add("Request method not supported.");
ApiErrorModel apiErrorModel = new ApiErrorModel(message, details, status, LocalDateTime.now());
return ResponseEntity.status(status).body(apiErrorModel);
}
@Override
protected ResponseEntity<Object> handleHttpMediaTypeNotSupported
(HttpMediaTypeNotSupportedException ex, HttpHeaders headers, HttpStatus status, WebRequest request)
{
String message = ex.getMessage();
List<String> details = new ArrayList<>();
details.add("Media method not supported.");
ApiErrorModel apiErrorModel = new ApiErrorModel(message, details, status, LocalDateTime.now());
return ResponseEntity.status(status).body(apiErrorModel);
}
@Override
protected ResponseEntity<Object> handleMissingPathVariable
(MissingPathVariableException ex, HttpHeaders headers, HttpStatus status, WebRequest request)
{
String message = ex.getMessage();
List<String> details = new ArrayList<>();
details.add("Path variable is missing.");
ApiErrorModel apiErrorModel = new ApiErrorModel(message, details, status, LocalDateTime.now());
return ResponseEntity.status(status).body(apiErrorModel);
}
@Override
protected ResponseEntity<Object> handleMissingServletRequestParameter
(MissingServletRequestParameterException ex, HttpHeaders headers, HttpStatus status, WebRequest request)
{
String message = ex.getMessage();
List<String> details = new ArrayList<>();
details.add("Request parameter is missing.");
ApiErrorModel apiErrorModel = new ApiErrorModel(message, details, status, LocalDateTime.now());
return ResponseEntity.status(status).body(apiErrorModel);
}
@Override
protected ResponseEntity<Object> handleTypeMismatch
(TypeMismatchException ex, HttpHeaders headers, HttpStatus status, WebRequest request)
{
String message = ex.getMessage();
List<String> details = new ArrayList<>();
details.add("Mismatch of type.");
ApiErrorModel apiErrorModel = new ApiErrorModel(message, details, status, LocalDateTime.now());
return ResponseEntity.status(status).body(apiErrorModel);
}
@Override
protected ResponseEntity<Object> handleHttpMessageNotReadable
(HttpMessageNotReadableException ex, HttpHeaders headers, HttpStatus status, WebRequest request)
{
String message = ex.getMessage();
List<String> details = new ArrayList<>();
details.add("Request body is not readable.");
ApiErrorModel apiErrorModel = new ApiErrorModel(message, details, status, LocalDateTime.now());
return ResponseEntity.status(status).body(apiErrorModel);
}
@ExceptionHandler(EmployeeNotFoundException.class)
public ResponseEntity<Object> handleEmployeeNotFoundException(EmployeeNotFoundException ex)
{
String message = ex.getMessage();
List<String> details = new ArrayList<>();
details.add("Employee not found.");
ApiErrorModel apiErrorModel = new ApiErrorModel(message, details, HttpStatus.BAD_REQUEST, LocalDateTime.now());
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(apiErrorModel);
}
@ExceptionHandler(CNPNotFoundException.class)
public ResponseEntity<Object> handleInvalidCNPException(CNPNotFoundException ex)
{
String message = ex.getMessage();
List<String> details = new ArrayList<>();
details.add("Employee with the given CNP not found.");
ApiErrorModel apiErrorModel = new ApiErrorModel(message, details, HttpStatus.NOT_FOUND, LocalDateTime.now());
return ResponseEntity.status(HttpStatus.NOT_FOUND).body(apiErrorModel);
}
}
CNPNotFoundException class:
package exception.requestsexceptions;
public class CNPNotFoundException extends RuntimeException
{
public CNPNotFoundException(String message) { super(message); }
}
ApiErrorModel class:
package exception.requestsexceptions;
import lombok.*;
import org.springframework.http.HttpStatus;
import java.time.LocalDateTime;
import java.util.List;
@Setter
@Getter
@NoArgsConstructor
@AllArgsConstructor
@ToString
public class ApiErrorModel
{
String message;
List<String> details;
HttpStatus status;
LocalDateTime timestamp;
}
我想像第二张图片中那样向用户提供一些相关信息,但在邮递员中,一切都保持在默认级别以这样调用它,就像我的处理程序代码甚至不存在一样。我是否遗漏了任何逻辑或注释?
This is how it looks on my side
This is how it should look like
感谢您的宝贵时间!
问题是当 class 被注释为 @SpringBootApplication
而没有任何属性时 SpringBoot 仅扫描 class 本身所在的包及其子包。
在您的情况下,这意味着 Spring当您将 GlobalExceptionHandler
class 放入 [=13] 时,引导仅查找 com.example.csmartbackend
包下的任何 Spring 组件=]s包。
要修复它,您有两种选择:
- 将
exception
包放在 com.example.csmartbackend 下,所以它将是com.example.csmartbackend.exception.requestsexception.GlobalExceptionHandler
- 告诉 spring 也扫描
exception
包,使用scanBasePackageClasses
或scanBasePackages
属性,例如@SpringBootApplication(scanBasePackageClasses = {CSmartBackEndApplication.class, GlobalExceptionHandler.class})