Respostas:
Desde o Spring 3.0, você também pode lançar uma exceção declarada com @ResponseStatus
anotação:
@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
é que você defina um monte de classes de exceção bem tipificadas e fortemente tipadas, cada uma com a sua @ResponseStatus
. Dessa forma, você separa o código do controlador dos detalhes dos códigos de status HTTP.
@ResponseStatus(value = HttpStatus.NOT_FOUND, reason="Your reason")
ResourceNotFound.fillInStackTrace()
por uma implementação vazia.
A partir do Spring 5.0, você não precisa necessariamente criar exceções adicionais:
throw new ResponseStatusException(NOT_FOUND, "Unable to find resource");
Além disso, você pode cobrir vários cenários com uma exceção integrada e ter mais controle.
Ver mais:
Reescreva sua assinatura de método para que ela aceite HttpServletResponse
como parâmetro, para que você possa acessá setStatus(int)
-la.
setStatus(int)
javadoc declara o seguinte: Se este método for usado para definir um código de erro, o mecanismo da página de erro do contêiner não será acionado. Se houver um erro e o chamador desejar chamar uma página de erro definida no aplicativo da web, ele sendError
deverá ser usado.
Gostaria de mencionar que há uma exceção (não apenas) para 404, por padrão, fornecida pelo Spring. Consulte a documentação do Spring para obter detalhes. Portanto, se você não precisar de sua própria exceção, basta fazer o seguinte:
@RequestMapping(value = "/**", method = RequestMethod.GET)
public ModelAndView show() throws NoSuchRequestHandlingMethodException {
if(something == null)
throw new NoSuchRequestHandlingMethodException("show", YourClass.class);
...
}
@PathVariable
não há tratamento de solicitações do meu ponto de vista. Você acha que é melhor / mais limpo usar sua própria exceção anotada @ResponseStatus(value = HttpStatus.NOT_FOUND)
?
Desde o Spring 3.0.2, você pode retornar o ResponseEntity <T> como resultado do método do controlador:
@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> é mais flexível que a anotação @ResponseBody - veja outra pergunta )
você pode usar o @ControllerAdvice para lidar com suas exceções. O comportamento padrão da classe anotada @ControllerAdvice ajudará todos os controladores conhecidos.
por isso, será chamado quando qualquer controlador que você lança erro 404.
como o seguinte:
@ControllerAdvice
class GlobalControllerExceptionHandler {
@ResponseStatus(HttpStatus.NOT_FOUND) // 404
@ExceptionHandler(Exception.class)
public void handleNoTFound() {
// Nothing to do
}
}
e mapeie esse erro de resposta 404 no seu web.xml, como o seguinte:
<error-page>
<error-code>404</error-code>
<location>/Error404.html</location>
</error-page>
Espero que ajude .
Se o método do seu controlador for para algo como manipulação de arquivos, ResponseEntity
é muito útil:
@Controller
public class SomeController {
@RequestMapping.....
public ResponseEntity handleCall() {
if (isFound()) {
return new ResponseEntity(...);
}
else {
return new ResponseEntity(404);
}
}
}
Embora a resposta marcada esteja correta, há uma maneira de conseguir isso sem exceções. O serviço está retornando Optional<T>
do objeto pesquisado e isso é mapeado para HttpStatus.OK
se encontrado e para 404 se estiver vazio.
@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);
}
}
Eu recomendo lançar HttpClientErrorException , como este
@RequestMapping(value = "/sample/")
public void sample() {
if (somethingIsWrong()) {
throw new HttpClientErrorException(HttpStatus.NOT_FOUND);
}
}
Você deve se lembrar que isso só pode ser feito antes que algo seja gravado no fluxo de saída do servlet.
Whitelabel Error Page \n .... \n There was an unexpected error (type=Internal Server Error, status=500). \n 404 This is your not found error
É um pouco tarde, mas se você estiver usando o Spring Data REST , já existe. org.springframework.data.rest.webmvc.ResourceNotFoundException
Ele também usa @ResponseStatus
anotação. Não há mais necessidade de criar uma exceção de tempo de execução customizada.
Além disso, se você deseja retornar o status 404 do seu controlador, tudo o que você precisa é fazer isso
@RequestMapping(value = "/somthing", method = RequestMethod.POST)
@ResponseBody
public HttpStatus doSomthing(@RequestBody String employeeId) {
try{
return HttpStatus.OK;
}
catch(Exception ex){
return HttpStatus.NOT_FOUND;
}
}
Ao fazer isso, você receberá um erro 404 no caso em que deseja retornar um 404 do seu controlador.
Simplesmente você pode usar o web.xml para adicionar código de erro e página de erro 404. Mas verifique se a página de erro 404 não deve ser localizada em WEB-INF.
<error-page>
<error-code>404</error-code>
<location>/404.html</location>
</error-page>
Essa é a maneira mais simples de fazer isso, mas isso tem algumas limitações. Suponha que, se você deseja adicionar o mesmo estilo para esta página, você adicionou outras páginas. Desta forma, você não pode fazer isso. Você tem que usar o@ResponseStatus(value = HttpStatus.NOT_FOUND)
HttpServletResponse#sendError(HttpServletResponse.SC_NOT_FOUND); return null;
partir do código do controlador. Agora, do lado de fora, a resposta não parece diferente de um 404 normal que não atingiu nenhum controlador.
Configure web.xml com a configuração
<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>
Criar novo controlador
/**
* 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;
}
}
Porque é sempre bom ter pelo menos dez maneiras de fazer a mesma coisa:
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);
}
}