Antworten:
Seit Spring 3.0 können Sie auch eine mit @ResponseStatus
Anmerkungen deklarierte Ausnahme auslösen:
@ResponseStatus(value = HttpStatus.NOT_FOUND)
public class ResourceNotFoundException extends RuntimeException {
...
}
@Controller
public class SomeController {
@RequestMapping.....
public void handleCall() {
if (isFound()) {
// whatever
}
else {
throw new ResourceNotFoundException();
}
}
}
@ResponseStatus
ist, dass Sie eine ganze Reihe von stark typisierten, gut benannten Ausnahmeklassen definieren, jede mit ihren eigenen @ResponseStatus
. Auf diese Weise entkoppeln Sie Ihren Controller-Code von den Details der HTTP-Statuscodes.
@ResponseStatus(value = HttpStatus.NOT_FOUND, reason="Your reason")
ResourceNotFound.fillInStackTrace()
mit einer leeren Implementierung zu überschreiben .
Ab Spring 5.0 müssen Sie nicht unbedingt zusätzliche Ausnahmen erstellen:
throw new ResponseStatusException(NOT_FOUND, "Unable to find resource");
Sie können auch mehrere Szenarien mit einer integrierten Ausnahme abdecken und haben mehr Kontrolle.
Mehr sehen:
Schreiben Sie Ihre Methodensignatur so um, dass sie HttpServletResponse
als Parameter akzeptiert wird, damit Sie sie aufrufen setStatus(int)
können.
setStatus(int)
javadoc gibt Folgendes an: Wenn diese Methode zum Festlegen eines Fehlercodes verwendet wird, wird der Fehlerseitenmechanismus des Containers nicht ausgelöst. Wenn ein Fehler vorliegt und der Anrufer eine in der Webanwendung definierte Fehlerseite aufrufen möchte, sendError
muss diese stattdessen verwendet werden.
Ich möchte erwähnen, dass es standardmäßig eine Ausnahme (nicht nur) für 404 gibt, die von Spring bereitgestellt wird. Weitere Informationen finden Sie in der Spring-Dokumentation . Wenn Sie also keine eigene Ausnahme benötigen, können Sie dies einfach tun:
@RequestMapping(value = "/**", method = RequestMethod.GET)
public ModelAndView show() throws NoSuchRequestHandlingMethodException {
if(something == null)
throw new NoSuchRequestHandlingMethodException("show", YourClass.class);
...
}
@PathVariable
gibt es aus meiner Sicht keine Anforderungsbearbeitung. Denken Sie, dass es besser / sauberer ist, eine eigene Ausnahme zu verwenden, die mit Anmerkungen versehen ist @ResponseStatus(value = HttpStatus.NOT_FOUND)
?
Seit Spring 3.0.2 können Sie ResponseEntity <T> als Ergebnis der Controller-Methode zurückgeben:
@RequestMapping.....
public ResponseEntity<Object> handleCall() {
if (isFound()) {
// do what you want
return new ResponseEntity<>(HttpStatus.OK);
}
else {
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
}
}
(ResponseEntity <T> ist flexibler als die @ ResponseBody-Annotation - siehe eine andere Frage )
Sie können das @ControllerAdvice verwenden , um Ihre Ausnahmen zu behandeln. Das Standardverhalten der mit @ControllerAdvice kommentierten Klasse unterstützt alle bekannten Controller.
Daher wird es aufgerufen, wenn ein Controller, den Sie haben, einen 404-Fehler auslöst.
wie folgt:
@ControllerAdvice
class GlobalControllerExceptionHandler {
@ResponseStatus(HttpStatus.NOT_FOUND) // 404
@ExceptionHandler(Exception.class)
public void handleNoTFound() {
// Nothing to do
}
}
und ordnen Sie diesen 404-Antwortfehler in Ihrer web.xml wie folgt zu:
<error-page>
<error-code>404</error-code>
<location>/Error404.html</location>
</error-page>
Hoffentlich hilft das .
Wenn Ihre Controller-Methode für die Dateiverwaltung vorgesehen ist, ResponseEntity
ist dies sehr praktisch:
@Controller
public class SomeController {
@RequestMapping.....
public ResponseEntity handleCall() {
if (isFound()) {
return new ResponseEntity(...);
}
else {
return new ResponseEntity(404);
}
}
}
Obwohl die markierte Antwort korrekt ist, gibt es eine Möglichkeit, dies ausnahmslos zu erreichen. Der Dienst gibt Optional<T>
das gesuchte Objekt zurück und dieses wird zugeordnet, HttpStatus.OK
wenn es gefunden wird, und 404, wenn es leer ist.
@Controller
public class SomeController {
@RequestMapping.....
public ResponseEntity<Object> handleCall() {
return service.find(param).map(result -> new ResponseEntity<>(result, HttpStatus.OK))
.orElse(new ResponseEntity<>(HttpStatus.NOT_FOUND));
}
}
@Service
public class Service{
public Optional<Object> find(String param){
if(!found()){
return Optional.empty();
}
...
return Optional.of(data);
}
}
Ich würde empfehlen, HttpClientErrorException wie folgt auszulösen
@RequestMapping(value = "/sample/")
public void sample() {
if (somethingIsWrong()) {
throw new HttpClientErrorException(HttpStatus.NOT_FOUND);
}
}
Sie müssen sich daran erinnern, dass dies nur möglich ist, bevor etwas in den Servlet-Ausgabestream geschrieben wird.
Whitelabel Error Page \n .... \n There was an unexpected error (type=Internal Server Error, status=500). \n 404 This is your not found error
Dies ist etwas spät, aber wenn Sie Spring Data REST verwenden, gibt es bereits org.springframework.data.rest.webmvc.ResourceNotFoundException
eine @ResponseStatus
Annotation. Es ist nicht mehr erforderlich, eine benutzerdefinierte Laufzeitausnahme zu erstellen.
Auch wenn Sie den 404-Status von Ihrem Controller zurückgeben möchten, müssen Sie dies nur tun
@RequestMapping(value = "/somthing", method = RequestMethod.POST)
@ResponseBody
public HttpStatus doSomthing(@RequestBody String employeeId) {
try{
return HttpStatus.OK;
}
catch(Exception ex){
return HttpStatus.NOT_FOUND;
}
}
Auf diese Weise erhalten Sie einen 404-Fehler, falls Sie einen 404 von Ihrem Controller zurückgeben möchten.
Sie können einfach web.xml verwenden, um Fehlercode und 404-Fehlerseite hinzuzufügen. Stellen Sie jedoch sicher, dass sich die 404-Fehlerseite nicht unter WEB-INF befindet.
<error-page>
<error-code>404</error-code>
<location>/404.html</location>
</error-page>
Dies ist der einfachste Weg, dies hat jedoch einige Einschränkungen. Angenommen, Sie möchten für diese Seite denselben Stil hinzufügen, den Sie für andere Seiten hinzugefügt haben. Auf diese Weise können Sie nicht dazu. Sie müssen die verwenden@ResponseStatus(value = HttpStatus.NOT_FOUND)
HttpServletResponse#sendError(HttpServletResponse.SC_NOT_FOUND); return null;
anhand des Controller-Codes. Von außen sieht die Reaktion nicht anders aus als bei einem normalen 404, der keinen Controller getroffen hat.
Konfigurieren Sie web.xml mit der Einstellung
<error-page>
<error-code>500</error-code>
<location>/error/500</location>
</error-page>
<error-page>
<error-code>404</error-code>
<location>/error/404</location>
</error-page>
Erstellen Sie einen neuen Controller
/**
* Error Controller. handles the calls for 404, 500 and 401 HTTP Status codes.
*/
@Controller
@RequestMapping(value = ErrorController.ERROR_URL, produces = MediaType.APPLICATION_XHTML_XML_VALUE)
public class ErrorController {
/**
* The constant ERROR_URL.
*/
public static final String ERROR_URL = "/error";
/**
* The constant TILE_ERROR.
*/
public static final String TILE_ERROR = "error.page";
/**
* Page Not Found.
*
* @return Home Page
*/
@RequestMapping(value = "/404", produces = MediaType.APPLICATION_XHTML_XML_VALUE)
public ModelAndView notFound() {
ModelAndView model = new ModelAndView(TILE_ERROR);
model.addObject("message", "The page you requested could not be found. This location may not be current.");
return model;
}
/**
* Error page.
*
* @return the model and view
*/
@RequestMapping(value = "/500", produces = MediaType.APPLICATION_XHTML_XML_VALUE)
public ModelAndView errorPage() {
ModelAndView model = new ModelAndView(TILE_ERROR);
model.addObject("message", "The page you requested could not be found. This location may not be current, due to the recent site redesign.");
return model;
}
}
Weil es immer gut ist, mindestens zehn Möglichkeiten zu haben, dasselbe zu tun:
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
@Controller
public class Something {
@RequestMapping("/path")
public ModelAndView somethingPath() {
return new ModelAndView("/", HttpStatus.NOT_FOUND);
}
}