Как мне получить Spring 3.0, чтобы вызвать 404?
У меня есть контроллер с @RequestMapping(value = "/**", method = RequestMethod.GET)
и для некоторых URL-адресов, обращающихся к контроллеру, я хочу, чтобы в контейнере появилось 404.
Как мне получить Spring 3.0, чтобы вызвать 404?
У меня есть контроллер с @RequestMapping(value = "/**", method = RequestMethod.GET)
и для некоторых URL-адресов, обращающихся к контроллеру, я хочу, чтобы в контейнере появилось 404.
Так как Spring 3.0 вы также можете выбросить исключение с помощью @ResponseStatus
аннотация:
@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();
}
}
}
Перепишите подпись своего метода, чтобы он принял HttpServletResponse
в качестве параметра, чтобы вы могли называть setStatus(int)
на нем.
Я хотел бы упомянуть, что исключение (не только) для 404 по умолчанию предоставляется Spring. Подробнее см. Spring документация. Поэтому, если вам не нужно ваше собственное исключение, вы можете просто сделать это:
@RequestMapping(value = "/**", method = RequestMethod.GET)
public ModelAndView show() throws NoSuchRequestHandlingMethodException {
if(something == null)
throw new NoSuchRequestHandlingMethodException("show", YourClass.class);
...
}
Начиная с Spring 3.0.2 вы можете вернуть ResponseEntity <T> в результате метода контроллера:
@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> является более гибким, чем аннотация @ResponseBody - см. Другой вопрос)
вы можете использовать @ControllerAdvice для обработки своих Исключений, Поведение по умолчанию для аннотированного класса @ControllerAdvice поможет всем известным контроллерам.
поэтому он будет вызываться, если у любого контроллера, у которого есть ошибка 404.
как показано ниже:
@ControllerAdvice
class GlobalControllerExceptionHandler {
@ResponseStatus(HttpStatus.NOT_FOUND) // 404
@ExceptionHandler(Exception.class)
public void handleNoTFound() {
// Nothing to do
}
}
и сопоставьте эту ошибку ответа 404 в вашем web.xml, например:
<error-page>
<error-code>404</error-code>
<location>/Error404.html</location>
</error-page>
Надеюсь, что это поможет.
Если ваш метод контроллера предназначен для обработки файлов, то ResponseEntity
очень удобен:
@Controller
public class SomeController {
@RequestMapping.....
public ResponseEntity handleCall() {
if (isFound()) {
return new ResponseEntity(...);
}
else {
return new ResponseEntity(404);
}
}
}
Я бы рекомендовал бросить HttpClientErrorException, как этот
@RequestMapping(value = "/sample/")
public void sample() {
if (somethingIsWrong()) {
throw new HttpClientErrorException(HttpStatus.NOT_FOUND);
}
}
Вы должны помнить, что это можно сделать только до того, как все будет записано в выходной поток сервлета.
В то время как отмеченный ответ верен, существует способ достижения этого без исключений. Служба возвращает Optional<T>
искомого объекта, и она отображается в HttpStatus.OK
, если она найдена, и до 404, если она пуста.
@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);
}
}
Начиная с Spring 5.0, вам не обязательно создавать дополнительные исключения:
throw new ResponseStatusException(NOT_FOUND, "Unable to find resource");
Кроме того, вы можете охватить несколько сценариев одним встроенным исключением, и у вас будет больше контроля.
Узнать больше:
Это немного поздно, но если вы используете Spring Data REST, то уже есть org.springframework.data.rest.webmvc.ResourceNotFoundException
Также используется аннотация @ResponseStatus
. Больше нет необходимости создавать пользовательское исключение во время выполнения.
Также, если вы хотите вернуть 404 статус с вашего контроллера, вам нужно это сделать
@RequestMapping(value = "/somthing", method = RequestMethod.POST)
@ResponseBody
public HttpStatus doSomthing(@RequestBody String employeeId) {
try{
return HttpStatus.OK;
}
catch(Exception ex){
return HttpStatus.NOT_FOUND;
}
}
При этом вы получите ошибку 404 в случае, если вы хотите вернуть 404 из своего контроллера.
Просто вы можете использовать web.xml для добавления кода ошибки и страницы ошибки 404. Но убедитесь, что страница ошибки 404 не должна находиться под WEB-INF.
<error-page>
<error-code>404</error-code>
<location>/404.html</location>
</error-page>
Это самый простой способ сделать это, но это имеет некоторые ограничения. Предположим, если вы хотите добавить тот же стиль для этой страницы, что и другие страницы. Таким образом, вы не можете этого сделать. Вы должны использовать @ResponseStatus(value = HttpStatus.NOT_FOUND)
Настройте web.xml с настройкой
<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>
Создать новый контроллер
/**
* 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;
}
}
Потому что всегда хорошо иметь как минимум десять способов сделать одно и то же:
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);
}
}