Spring Boot Eliminar página de error Whitelabel


156

Estoy tratando de eliminar la página de error de etiqueta blanca, así que lo que hice fue crear una asignación de controlador para "/ error",

@RestController
public class IndexController {

    @RequestMapping(value = "/error")
    public String error() {
        return "Error handling";
    }

}

Pero ahora recibo este error.

Exception in thread "AWT-EventQueue-0" org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'requestMappingHandlerMapping' defined in class path resource   [org/springframework/web/servlet/config/annotation/DelegatingWebMvcConfiguration.class]: Invocation  of init method failed; nested exception is java.lang.IllegalStateException: Ambiguous mapping found. Cannot map 'basicErrorController' bean method 
public org.springframework.http.ResponseEntity<java.util.Map<java.lang.String, java.lang.Object>>  org.springframework.boot.autoconfigure.web.BasicErrorController.error(javax.servlet.http.HttpServletR equest)
to {[/error],methods=[],params=[],headers=[],consumes=[],produces=[],custom=[]}: There is already 'indexController' bean method

No sé si estoy haciendo algo mal. Por favor aconséjame.

EDITAR:

Ya se ha agregado error.whitelabel.enabled=false al archivo application.properties, pero sigue obteniendo el mismo error


1
Mire este proyecto github.com/paulc4/mvc-exceptions/blob/master/src/main/java/… , parece que tienen una reasignación de página de error.
Innot Kauker

¿Has intentado configurar spring.resources.add-mappings=false?
geoand

Gracias por la sugerencia, Sí todavía recibí el mismo error
Yasitha Waduge

¿Estás intentando devolver algún contenido personalizado cuando /errorse llama a la ruta?
geoand

Respuestas:


240

Necesita cambiar su código a lo siguiente:

@RestController
public class IndexController implements ErrorController{

    private static final String PATH = "/error";

    @RequestMapping(value = PATH)
    public String error() {
        return "Error handling";
    }

    @Override
    public String getErrorPath() {
        return PATH;
    }
}

Su código no funcionó, porque Spring Boot lo registra automáticamente BasicErrorControllercomo Spring Bean cuando no ha especificado una implementación de ErrorController.

Para ver ese hecho solo navega hasta ErrorMvcAutoConfiguration.basicErrorController aquí .


1
Me encontré con el mismo problema, busqué en los documentos de Spring pero no mencionó BasicErrorController. Esto funciona :)
Mike R

44
Tuve que revisar la fuente para encontrar este :-)
geoand

1
Gracias, funcionó muy bien! Un pequeño seguimiento si puede dar algunos indicadores: digamos que entramos en este controlador de errores porque se produjo alguna excepción en nuestra aplicación (y Spring establece implícitamente el código de respuesta en 500, que es correcto); ¿Hay alguna manera fácil de obtener esa excepción aquí (para incluir algunos detalles en el mensaje de error devuelto)?
Jonik

1
¡Me alegra que lo hayas encontrado útil! Aunque no lo he probado, estoy bastante seguro de que puede usar los principios que se encuentran en Spring Boot's BasicErrorController(consulte github.com/spring-projects/spring-boot/blob/… ) para lograr lo que desea
geoand

3
Hmm, sí, ¡gracias de nuevo! Al principio no estaba seguro de cómo obtener ese ErrorAttributesobjeto (que contiene los detalles del error), pero luego intenté simplemente @Autowiring y funciona. Lo que elegí
Jonik

44

Si desea una página de respuesta más "JSONish", puede intentar algo como eso:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.web.ErrorAttributes;
import org.springframework.boot.autoconfigure.web.ErrorController;
import org.springframework.util.Assert;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.util.Map;

@RestController
@RequestMapping("/error")
public class SimpleErrorController implements ErrorController {

  private final ErrorAttributes errorAttributes;

  @Autowired
  public SimpleErrorController(ErrorAttributes errorAttributes) {
    Assert.notNull(errorAttributes, "ErrorAttributes must not be null");
    this.errorAttributes = errorAttributes;
  }

  @Override
  public String getErrorPath() {
    return "/error";
  }

  @RequestMapping
  public Map<String, Object> error(HttpServletRequest aRequest){
     Map<String, Object> body = getErrorAttributes(aRequest,getTraceParameter(aRequest));
     String trace = (String) body.get("trace");
     if(trace != null){
       String[] lines = trace.split("\n\t");
       body.put("trace", lines);
     }
     return body;
  }

  private boolean getTraceParameter(HttpServletRequest request) {
    String parameter = request.getParameter("trace");
    if (parameter == null) {
        return false;
    }
    return !"false".equals(parameter.toLowerCase());
  }

  private Map<String, Object> getErrorAttributes(HttpServletRequest aRequest, boolean includeStackTrace) {
    RequestAttributes requestAttributes = new ServletRequestAttributes(aRequest);
    return errorAttributes.getErrorAttributes(requestAttributes, includeStackTrace);
  }
}

77
En Spring-Boot v2, las clases ErrorController y ErrorAttributes están en el paquete org.springframework.boot.web.servlet.error y además la firma del método ErrorAttributes # getErrorAttributes ha cambiado, tenga en cuenta la dependencia de Spring-Boot v1 y posiblemente dé pistas para v2, Gracias.
chrisinmtown

1
Cambio: mapa privado <String, Object> getErrorAttributes (HttpServletRequest aRequest, boolean includeStackTrace) {RequestAttributes requestAttributes = new ServletRequestAttributes (aRequest); return errorAttributes.getErrorAttributes (requestAttributes, includeStackTrace); } Por: mapa privado <String, Object> getErrorAttributes (solicitud HttpServletRequest, boolean includeStackTrace) {WebRequest webRequest = new ServletWebRequest (request); devuelve this.errorAttributes.getErrorAttributes (webRequest, includeStackTrace); }
Rija Ramampiandra

2
Una versión actualizada de SimpleErrorController.java considerando los comentarios de arriba se puede encontrar aquí> gist.github.com/oscarnevarezleal/…
Oscar Nevarez

38

Spring boot doc 'estaba' mal (lo han arreglado desde entonces):

Para desactivarlo, puede establecer error.whitelabel.enabled = false

debiera ser

Para desactivarlo, puede configurar server.error.whitelabel.enabled = false


Esto deshabilitará la página de error de etiqueta blanca, pero el inicio de primavera asignará el punto final de /errortodos modos. Para liberar el /errorconjunto de puntos finales server.error.path=/error-springo alguna ruta alternativa.
notes-jj

32

Puede eliminarlo completamente especificando:

import org.springframework.context.annotation.Configuration;
import org.springframework.boot.autoconfigure.web.servlet.error.ErrorMvcAutoConfiguration;
...
@Configuration
@EnableAutoConfiguration(exclude = {ErrorMvcAutoConfiguration.class})
public static MainApp { ... }

Sin embargo, tenga en cuenta que hacerlo probablemente hará que aparezcan las páginas de etiqueta blanca del contenedor de servlet :)


EDITAR: Otra forma de hacerlo es a través de application.yaml. Solo pon el valor:

spring:
  autoconfigure:
    exclude: org.springframework.boot.autoconfigure.web.servlet.error.ErrorMvcAutoConfiguration

Documentación

Para Spring Boot <2.0, la clase se encuentra en el paquete org.springframework.boot.autoconfigure.web.


15

Manual de aquí dice que usted tiene que fijar server.error.whitelabel.enableda falsedesactivar la página de error estándar. Tal vez es lo que quieres?

Por cierto, estoy experimentando el mismo error después de agregar / mapeo de errores.


Sí, ya configuré error.whitelabel.enabled = false pero sigo recibiendo el mismo error después de agregar / mapeo de errores
Yasitha Waduge

Esto deshabilitará la página de error de etiqueta blanca, pero el inicio de primavera asignará el punto final de /errortodos modos. Para liberar el /errorconjunto de puntos finales server.error.path=/error-springo alguna ruta alternativa.
notes-jj

11

Con Spring Boot> 1.4.x puedes hacer esto:

@SpringBootApplication(exclude = {ErrorMvcAutoConfiguration.class})
public class MyApi {
  public static void main(String[] args) {
    SpringApplication.run(App.class, args);
  }
}

pero luego, en caso de excepción, el contenedor de servlet mostrará su propia página de error.



6

En Spring Boot 1.4.1 con plantillas de bigote, basta con colocar error.html en la carpeta de plantillas:

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="utf-8">
  <title>Error</title>
</head>

<body>
  <h1>Error {{ status }}</h1>
  <p>{{ error }}</p>
  <p>{{ message }}</p>
  <p>{{ path }}</p>
</body>

</html>

Se pueden pasar variables adicionales creando un interceptor para /error



3

Aquí hay un método alternativo que es muy similar a la "forma antigua" de especificar asignaciones de error en web.xml.

Simplemente agregue esto a su configuración de Spring Boot:

@SpringBootApplication
public class Application implements WebServerFactoryCustomizer<ConfigurableServletWebServerFactory> {

    @Override
    public void customize(ConfigurableServletWebServerFactory factory) {
        factory.addErrorPages(new ErrorPage(HttpStatus.FORBIDDEN, "/errors/403.html"));
        factory.addErrorPages(new ErrorPage(HttpStatus.NOT_FOUND, "/errors/404.html"));
        factory.addErrorPages(new ErrorPage("/errors/500.html"));
    }

}

Luego puede definir las páginas de error en el contenido estático normalmente.

El personalizador también puede ser independiente @Component, si lo desea.


3

Estoy usando Spring Boot versión 2.1.2 y la errorAttributes.getErrorAttributes()firma no funcionó para mí (en respuesta de acohen). Quería una respuesta tipo JSON, así que investigué un poco y descubrí que este método hacía exactamente lo que necesitaba.

Obtuve la mayor parte de mi información de este hilo, así como de esta publicación de blog .

Primero, creé un CustomErrorControllerSpring que buscará para asignar cualquier error.

package com.example.error;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.web.servlet.error.ErrorAttributes;
import org.springframework.boot.web.servlet.error.ErrorController;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.context.request.WebRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.HashMap;
import java.util.Map;

@RestController
public class CustomErrorController implements ErrorController {

    private static final String PATH = "error";

    @Value("${debug}")
    private boolean debug;

    @Autowired
    private ErrorAttributes errorAttributes;

    @RequestMapping(PATH)
    @ResponseBody
    public CustomHttpErrorResponse error(WebRequest request, HttpServletResponse response) {
        return new CustomHttpErrorResponse(response.getStatus(), getErrorAttributes(request));
    }

    public void setErrorAttributes(ErrorAttributes errorAttributes) {
        this.errorAttributes = errorAttributes;
    }

    @Override
    public String getErrorPath() {
        return PATH;
    }

    private Map<String, Object> getErrorAttributes(WebRequest request) {
        Map<String, Object> map = new HashMap<>();
        map.putAll(this.errorAttributes.getErrorAttributes(request, this.debug));
        return map;
    }
}

En segundo lugar, creé una CustomHttpErrorResponseclase para devolver el error como JSON.

package com.example.error;

import java.util.Map;

public class CustomHttpErrorResponse {

    private Integer status;
    private String path;
    private String errorMessage;
    private String timeStamp;
    private String trace;

    public CustomHttpErrorResponse(int status, Map<String, Object> errorAttributes) {
        this.setStatus(status);
        this.setPath((String) errorAttributes.get("path"));
        this.setErrorMessage((String) errorAttributes.get("message"));
        this.setTimeStamp(errorAttributes.get("timestamp").toString());
        this.setTrace((String) errorAttributes.get("trace"));
    }

    // getters and setters
}

Finalmente, tuve que apagar Whitelabel en el application.propertiesarchivo.

server.error.whitelabel.enabled=false

Esto incluso debería funcionar para xmlsolicitudes / respuestas. Pero no he probado eso. Hizo exactamente lo que estaba buscando ya que estaba creando una API RESTful y solo quería devolver JSON.


2

server.error.whitelabel.enabled = false

Incluya la línea anterior a las carpetas de recursos application.properties

Más resolución de problema de error, consulte http://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#howto-customize-the-whitelabel-error-page


Intenté application.properties en mi carpeta de instalación que no hizo nada. La carpeta application.properties en / src / main / resources es lo que suganya sudarsan intentaba transmitir. Parece ser una "lectura en caliente" en Eclipse también.
Richard Bradley Smith

1

Estaba tratando de llamar a un punto final REST desde un microservicio y estaba usando el método put de resttemplate .

En mi diseño si se ha producido algún error en el interior del RESTO punto final que debe devolver una respuesta de error de JSON, que estaba trabajando para algunas llamadas, pero no para este puesto uno, volvió la página de error de marca blanca en su lugar.

Así que investigué un poco y descubrí eso;

Spring intenta entender a la persona que llama si es una máquina y luego devuelve la respuesta JSON o si se trata de un navegador que devuelve el HTML de la página de error de etiqueta blanca .

Como resultado: mi aplicación cliente necesitaba decirle al punto final REST que la persona que llama es una máquina, no un navegador, por lo que para esto la aplicación cliente necesitaba agregar ' application / json ' en el encabezado ACCEPT explícitamente para el método 'put' de la nueva plantilla. Agregué esto al encabezado y resolví el problema.

mi llamada al punto final:

restTemplate.put(url, request, param1, param2);

para la llamada anterior tuve que agregar debajo del parámetro de encabezado.

headers.set("Accept", MediaType.APPLICATION_JSON_UTF8_VALUE);

o traté de cambiar poner a cambio también, en este caso, la llamada de intercambio agregó el mismo encabezado para mí y resolvió el problema también, pero no sé por qué :)

restTemplate.exchange(....)

0

Spring Boot por defecto tiene una página de error de " etiqueta blanca " que puede ver en un navegador si encuentra un error del servidor. Whitelabel Error Page es una página genérica de error de Spring Boot que se muestra cuando no se encuentra una página de error personalizada.

Establezca "server.error.whitelabel.enabled = false" para cambiar de la página de error predeterminada


0

Tenía un mensaje de error WhiteLabel de problema similar en mi Angular SPA cada vez que hacía una actualización.

La solución fue crear un controlador que implemente ErrorController pero en lugar de devolver una Cadena, tuve que devolver un objeto ModelAndView que reenvía a /

@CrossOrigin
@RestController
public class IndexController implements ErrorController {
    
    private static final String PATH = "/error";
    
    @RequestMapping(value = PATH)
    public ModelAndView saveLeadQuery() {           
        return new ModelAndView("forward:/");
    }

    @Override
    public String getErrorPath() {
        return PATH;
    }
}
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.