如何在 spring 启动时验证 rest url?
How to validated rest url in spring boot?
在 spring 引导中验证 Rest URL。
要求:如果我打错了 URL 那么它应该抛出一个自定义异常。
前任。正确的 URL 是“/fulfillment/600747l/send_to_hub” 如果我点击“/api/600747l/send_to_hub_1” 那么它应该 return 例外
“404:- URL 未找到。”。
现在 returning "500 : -
{
"timestamp": 1531995246549,
"status": 500,
"error": "Internal Server Error",
"message": "Invalid Request URL.",
"path": "/api/600747l/send_to_hub_1"
}"
根据您的问题,首先您需要定义一个基数 url(例如-/api),以便任何 url 都必须通过您的 controller.Now 在基础 url 之后,如图所示 /api/600747l/send_to_hub_1 @PathVariable int id。这种情况很重要,因为 Spring 文档说如果用 @PathVariable 注释的方法参数不能转换为指定类型(在我们的例子中为 int),它将被暴露为 String。因此它可能导致 TypeMismatchException。
为了处理这个问题,我将在@Controller 级别使用@ExceptionHandler 注释。这种方法最适合这种情况。我只需要在控制器中进行 2 处更改:
1.Add 消息源字段
2.Add 异常处理方法
@Autowired
private MessageSource messageSource;
...
@ExceptionHandler(TypeMismatchException.class)
@ResponseStatus(value=HttpStatus.NOT_FOUND)
@ResponseBody
public ErrorInfo handleTypeMismatchException(HttpServletRequest req, TypeMismatchException ex) {
Locale locale = LocaleContextHolder.getLocale();
String errorMessage = messageSource.getMessage("error.bad.smartphone.id", null, locale);
errorMessage += ex.getValue();
String errorURL = req.getRequestURL().toString();
return new ErrorInfo(errorURL, errorMessage);
}
...
你需要用注解@ControllerAdvice 编写 NewClass,它将所有异常重定向到这个 NewClass。
例子
您的自定义异常 Class:
@Data
@AllArgsConstructor
@EqualsAndHashCode(callSuper = false)
public class IOApiException extends IOException {
private ErrorReason errorReason;
public IOApiException(String message, ErrorReason errorReason) {
super(message);
this.errorReason = errorReason;
}
}
现在是 CustomExceptionHandler Class -
@ControllerAdvice
@RestController
public class GlobalExceptionHandler {
Logger logger = LoggerFactory.getLogger(this.getClass());
@ResponseStatus(HttpStatus.UNAUTHORIZED)
@ExceptionHandler(value = IOApiException.class)
public GlobalErrorResponse handleException(IOApiException e) {
logger.error("UNAUTHORIZED: ", e);
return new GlobalErrorResponse("URL Not Found", HttpStatus.UNAUTHORIZED.value(), e.getErrorReason());
}
//this to handle customErrorResponseClasses
public GlobalErrorResponse getErrorResponseFromGenericException(Exception ex) {
if (ex == null) {
return handleException(new Exception("INTERNAL_SERVER_ERROR"));
}
else if (ex instanceof IOApiException) {
return handleException((IOApiException) ex);
}
}
现在你的错误回复class:
public class GlobalErrorResponse {
private String message;
@JsonIgnore
private int statusCode;
private ErrorReason reason;
}
错误原因Class
public enum ErrorReason {
INTERNAL_SERVER_ERROR,
INVALID_REQUEST_PARAMETER,
INVALID_URL
}
添加并注册一个在异常情况下调用 GlobalExceptionHandler 的过滤器
public class ExceptionHandlerFilter implements Filter {
private final GlobalExceptionHandler globalExceptionHandler;
public ExceptionHandlerFilter(GlobalExceptionHandler globalExceptionHandler) {
this.globalExceptionHandler = globalExceptionHandler;
}
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
try {
chain.doFilter(request, response);
} catch (Exception exception) {
HttpServletResponse httpResponse = (HttpServletResponse) response;
GlobalErrorResponse errorResponse = globalExceptionHandler.getErrorResponseFromGenericException(exception);
httpResponse.setStatus(errorResponse.getStatusCode());
response.getWriter().write(new ObjectMapper().writeValueAsString(errorResponse));
}
}
@Override
public void destroy() {
}
}
像这样你可以添加任意数量的异常..并且可以手动处理它。
在 spring 引导中验证 Rest URL。 要求:如果我打错了 URL 那么它应该抛出一个自定义异常。 前任。正确的 URL 是“/fulfillment/600747l/send_to_hub” 如果我点击“/api/600747l/send_to_hub_1” 那么它应该 return 例外 “404:- URL 未找到。”。
现在 returning "500 : -
{
"timestamp": 1531995246549,
"status": 500,
"error": "Internal Server Error",
"message": "Invalid Request URL.",
"path": "/api/600747l/send_to_hub_1"
}"
根据您的问题,首先您需要定义一个基数 url(例如-/api),以便任何 url 都必须通过您的 controller.Now 在基础 url 之后,如图所示 /api/600747l/send_to_hub_1 @PathVariable int id。这种情况很重要,因为 Spring 文档说如果用 @PathVariable 注释的方法参数不能转换为指定类型(在我们的例子中为 int),它将被暴露为 String。因此它可能导致 TypeMismatchException。
为了处理这个问题,我将在@Controller 级别使用@ExceptionHandler 注释。这种方法最适合这种情况。我只需要在控制器中进行 2 处更改:
1.Add 消息源字段 2.Add 异常处理方法
@Autowired
private MessageSource messageSource;
...
@ExceptionHandler(TypeMismatchException.class)
@ResponseStatus(value=HttpStatus.NOT_FOUND)
@ResponseBody
public ErrorInfo handleTypeMismatchException(HttpServletRequest req, TypeMismatchException ex) {
Locale locale = LocaleContextHolder.getLocale();
String errorMessage = messageSource.getMessage("error.bad.smartphone.id", null, locale);
errorMessage += ex.getValue();
String errorURL = req.getRequestURL().toString();
return new ErrorInfo(errorURL, errorMessage);
}
...
你需要用注解@ControllerAdvice 编写 NewClass,它将所有异常重定向到这个 NewClass。 例子
您的自定义异常 Class:
@Data
@AllArgsConstructor
@EqualsAndHashCode(callSuper = false)
public class IOApiException extends IOException {
private ErrorReason errorReason;
public IOApiException(String message, ErrorReason errorReason) {
super(message);
this.errorReason = errorReason;
}
}
现在是 CustomExceptionHandler Class -
@ControllerAdvice
@RestController
public class GlobalExceptionHandler {
Logger logger = LoggerFactory.getLogger(this.getClass());
@ResponseStatus(HttpStatus.UNAUTHORIZED)
@ExceptionHandler(value = IOApiException.class)
public GlobalErrorResponse handleException(IOApiException e) {
logger.error("UNAUTHORIZED: ", e);
return new GlobalErrorResponse("URL Not Found", HttpStatus.UNAUTHORIZED.value(), e.getErrorReason());
}
//this to handle customErrorResponseClasses
public GlobalErrorResponse getErrorResponseFromGenericException(Exception ex) {
if (ex == null) {
return handleException(new Exception("INTERNAL_SERVER_ERROR"));
}
else if (ex instanceof IOApiException) {
return handleException((IOApiException) ex);
}
}
现在你的错误回复class:
public class GlobalErrorResponse {
private String message;
@JsonIgnore
private int statusCode;
private ErrorReason reason;
}
错误原因Class
public enum ErrorReason {
INTERNAL_SERVER_ERROR,
INVALID_REQUEST_PARAMETER,
INVALID_URL
}
添加并注册一个在异常情况下调用 GlobalExceptionHandler 的过滤器
public class ExceptionHandlerFilter implements Filter {
private final GlobalExceptionHandler globalExceptionHandler;
public ExceptionHandlerFilter(GlobalExceptionHandler globalExceptionHandler) {
this.globalExceptionHandler = globalExceptionHandler;
}
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
try {
chain.doFilter(request, response);
} catch (Exception exception) {
HttpServletResponse httpResponse = (HttpServletResponse) response;
GlobalErrorResponse errorResponse = globalExceptionHandler.getErrorResponseFromGenericException(exception);
httpResponse.setStatus(errorResponse.getStatusCode());
response.getWriter().write(new ObjectMapper().writeValueAsString(errorResponse));
}
}
@Override
public void destroy() {
}
}
像这样你可以添加任意数量的异常..并且可以手动处理它。