Spring Boot Remove Whitelabel Error Strona

156

Próbuję usunąć stronę błędu białej etykiety, więc stworzyłem mapowanie kontrolera dla "/ error",

@RestController
public class IndexController {

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

}

Ale teraz pojawia się ten błąd.

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

Nie wiem, czy robię coś złego. Proszę o poradę.

EDYTOWAĆ:

Już dodane error.whitelabel.enabled=false do pliku application.properties, nadal pojawia się ten sam błąd

Yasitha Waduge
źródło
1
Spójrz na ten projekt github.com/paulc4/mvc-exceptions/blob/master/src/main/java/… , wygląda na to , że mają w nim mapowanie strony błędu.
Innot Kauker
Czy próbowałeś ustawić spring.resources.add-mappings=false?
geoand
Dziękuję za sugestię, tak, nadal występuje ten sam błąd
Yasitha Waduge
Czy po prostu próbujesz zwrócić niestandardową zawartość po /errorwywołaniu ścieżki?
geoand

Odpowiedzi:

240

Musisz zmienić kod na następujący:

@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;
    }
}

Twój kod nie zadziałał, ponieważ Spring Boot automatycznie rejestruje BasicErrorControllerjako Spring Bean, gdy nie określono implementacji ErrorController.

Aby zobaczyć ten fakt, przejdź do ErrorMvcAutoConfiguration.basicErrorController tego miejsca .

geoand
źródło
1
Wpadłem na ten sam problem, przeszukałem dokumentację Springa, ale nie wspomniał o BasicErrorController. To działa :)
Mike R
4
Musiałem przejrzeć źródło, aby znaleźć to :-)
geo i
1
Dzięki, ładnie działało! Mała kontynuacja, jeśli możesz podać jakieś wskazówki: powiedz, że otrzymujemy ten program obsługi błędów, ponieważ w naszej aplikacji został zgłoszony wyjątek (a Spring niejawnie ustawia kod odpowiedzi na 500, który jest poprawny); czy istnieje tutaj łatwy sposób na uzyskanie tego wyjątku (w celu uwzględnienia niektórych szczegółów w zwracanym komunikacie o błędzie)?
Jonik
1
Cieszę się, że znalazłeś to przydatne! Chociaż nie próbowałem tego, jestem prawie pewien, że możesz użyć zasad znalezionych w Spring Boot's BasicErrorController(patrz github.com/spring-projects/spring-boot/blob/ ... ), aby osiągnąć to, co chcesz
geoand
3
Hmm, tak, jeszcze raz dziękuję! Na początku nie byłem pewien, jak zdobyć ten ErrorAttributesobiekt (zawierający szczegóły błędu), ale potem wypróbowałem po prostu @Autowiring i działa. Z czym na razie poszedłem
Jonik
44

Jeśli chcesz mieć stronę odpowiedzi bardziej „JSONish”, możesz spróbować czegoś takiego:

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);
  }
}
acohen
źródło
7
W Spring-Boot v2 klasy ErrorController i ErrorAttributes znajdują się w pakiecie org.springframework.boot.web.servlet.error, a ponadto zmieniła się sygnatura metody ErrorAttributes # getErrorAttributes. dzięki.
chrisinmtown
1
Zmiana: prywatna Map <String, Object> getErrorAttributes (HttpServletRequest aRequest, boolean includeStackTrace) {RequestAttributes requestAttributes = new ServletRequestAttributes (aRequest); return errorAttributes.getErrorAttributes (requestAttributes, includeStackTrace); } By: private Map <String, Object> getErrorAttributes (żądanie HttpServletRequest, boolean includeStackTrace) {WebRequest webRequest = new ServletWebRequest (żądanie); return this.errorAttributes.getErrorAttributes (webRequest, includeStackTrace); }
Rija Ramampiandra
2
Zaktualizowaną wersję SimpleErrorController.java, biorąc pod uwagę powyższe komentarze, można znaleźć tutaj> gist.github.com/oscarnevarezleal/…
Oscar
38

Dokument rozruchowy sprężyny „był” nieprawidłowy (od tego czasu go naprawili):

Aby go wyłączyć, możesz ustawić error.whitelabel.enabled = false

Powinien być

Aby go wyłączyć, możesz ustawić server.error.whitelabel.enabled = false

willome
źródło
Spowoduje to wyłączenie strony błędów White Label, ale rozruch sprężynowy i /errortak mapuje punkt końcowy . Aby zwolnić /errorzestaw punktów końcowych server.error.path=/error-springlub inną ścieżkę alternatywną.
notatki-jj
32

Możesz go całkowicie usunąć, określając:

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

Należy jednak pamiętać, że zrobienie tego prawdopodobnie spowoduje wyświetlenie stron z białym etykietą kontenera serwletów :)


EDYCJA: Innym sposobem na zrobienie tego jest użycie pliku application.yaml. Po prostu wpisz wartość:

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

Dokumentacja

W przypadku Spring Boot <2.0 klasa znajduje się w pakiecie org.springframework.boot.autoconfigure.web.

hoodieman
źródło
15

Instrukcja tutaj mówi, że trzeba ustawić server.error.whitelabel.enabled, aby falsewyłączyć standardową stronę błędu. Może tego chcesz?

Nawiasem mówiąc, mam ten sam błąd po dodaniu / mapowaniu błędów.

Innot Kauker
źródło
Tak, już ustawiłem error.whitelabel.enabled = false, ale nadal pojawia się ten sam błąd po dodaniu / mapowaniu błędów
Yasitha Waduge
Spowoduje to wyłączenie strony błędów White Label, ale rozruch sprężynowy i /errortak mapuje punkt końcowy . Aby zwolnić /errorzestaw punktów końcowych server.error.path=/error-springlub inną ścieżkę alternatywną.
notatki-jj
11

Przy Spring Boot> 1.4.x możesz to zrobić:

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

ale wtedy w przypadku wyjątku kontener serwletu wyświetli własną stronę błędu.

db80
źródło
6

W Spring Boot 1.4.1 przy użyciu szablonów Mustache wystarczy umieścić error.html w folderze szablonów:

<!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>

Dodatkowe zmienne można przekazać, tworząc przechwytywacz dla /error

Ecmel Ercan
źródło
3

Oto alternatywna metoda, która jest bardzo podobna do „starego sposobu” określania mapowań błędów w programie web.xml.

Po prostu dodaj to do konfiguracji 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"));
    }

}

Następnie możesz normalnie zdefiniować strony błędów w treści statycznej.

W @Componentrazie potrzeby moduł dostosowywania może być również oddzielny .

rustyx
źródło
3

Używam Spring Boot w wersji 2.1.2 i errorAttributes.getErrorAttributes()podpis nie działa dla mnie (w odpowiedzi acohen). Chciałem odpowiedzi typu JSON, więc trochę poszperałem i stwierdziłem, że ta metoda zrobiła dokładnie to, czego potrzebowałem.

Większość informacji uzyskałem z tego wątku, a także z tego wpisu na blogu .

Najpierw utworzyłem obiekt, CustomErrorControllerktórego Spring będzie szukał, aby zmapować wszelkie błędy.

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;
    }
}

Po drugie, utworzyłem CustomHttpErrorResponseklasę, która zwraca błąd jako 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
}

Wreszcie musiałem wyłączyć Whitelabel w application.propertiespliku.

server.error.whitelabel.enabled=false

Powinno to działać nawet w przypadku xmlpróśb / odpowiedzi. Ale ja tego nie testowałem. Zrobił dokładnie to, czego szukałem, odkąd tworzyłem RESTful API i chciałem tylko zwrócić JSON.

DJ House
źródło
2

server.error.whitelabel.enabled = false

Dołącz powyższy wiersz do application.properties folderów zasobów

Więcej rozwiązywania problemów z błędami można znaleźć na http://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#howto-customize-the-whitelabel-error-page

suganya sudarsan
źródło
Próbowałem application.properties w moim folderze instalacyjnym, co nic nie dało. Folder application.properties w / src / main / resources jest tym, co próbował przekazać suganya sudarsan. Wydaje się, że jest to również „gorąca lektura” w Eclipse.
Richard Bradley Smith
1

Próbowałem wywołać punkt końcowy REST z mikrousługi i używałem metody put resttemplate .

W mojej konstrukcji, jeśli wystąpił jakiś błąd wewnątrz REST punktu końcowego powinien powrócić odpowiedź błędzie JSON, że pracuje dla niektórych połączeń, ale nie do tego umieścić jeden, to zwrócił white label stronę błędu zamiast.

Zrobiłem więc śledztwo i dowiedziałem się, że;

Sprężyna próbuje zrozumieć wywołującego, czy jest to maszyna, a następnie zwraca odpowiedź JSON, a jeśli jest to przeglądarka, zwraca kod HTML strony błędu białej etykiety .

W rezultacie: moja aplikacja kliencka musiała powiedzieć punktowi końcowemu REST, że wywołujący jest maszyną, a nie przeglądarką, więc w tym celu aplikacja klienta musiała dodać „ application / json ” do nagłówka ACCEPT wyraźnie dla metody „put” resttemplate. Dodałem to do nagłówka i rozwiązałem problem.

moje wywołanie punktu końcowego:

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

dla powyższego wywołania musiałem dodać poniżej parametr nagłówka.

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

czy też próbowałem zmienić put na wymianę, w tym przypadku połączenie wymiany dodało mi ten sam nagłówek i też rozwiązało problem, ale nie wiem dlaczego :)

restTemplate.exchange(....)
cazador
źródło
0

Spring Boot domyślnie ma stronę błędu „ whiteabel ”, którą możesz zobaczyć w przeglądarce, jeśli napotkasz błąd serwera. Strona błędu Whitelabel to ogólna strona błędu Spring Boot, która jest wyświetlana, gdy nie zostanie znaleziona niestandardowa strona błędu.

Ustaw „server.error.whitelabel.enabled = false”, aby przełączyć domyślną stronę błędu

shatakshi
źródło
0

Miałem podobny problem z komunikatem o błędzie WhiteLabel na moim Angular SPA za każdym razem, gdy wykonałem odświeżenie.

Rozwiązaniem było utworzenie kontrolera, który implementuje ErrorController, ale zamiast zwracać String, musiałem zwrócić obiekt ModelAndView, który przekazuje do /

@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;
    }
}
Shubhashish Mishra
źródło