Як отримати контролер 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();
}
}
}
@ResponseStatus
полягає в тому, що ви визначаєте цілу купу сильно типізованих, добре названих класів винятків, кожен з яких має свої власні @ResponseStatus
. Таким чином, ви відокремлюєте код свого контролера від деталей кодів статусу HTTP.
@ResponseStatus(value = HttpStatus.NOT_FOUND, reason="Your reason")
ResourceNotFound.fillInStackTrace()
порожню реалізацію.
Починаючи з весни 5.0, вам не обов’язково створювати додаткові винятки:
throw new ResponseStatusException(NOT_FOUND, "Unable to find resource");
Крім того, ви можете охопити декілька сценаріїв одним вбудованим винятком і мати більше контролю.
Побачити більше:
Перепишіть свій підпис методу, щоб він прийняв HttpServletResponse
як параметр, щоб ви могли зателефонувати setStatus(int)
на нього.
setStatus(int)
javadoc заявляє так: Якщо цей метод використовується для встановлення коду помилки, механізм сторінки помилок контейнера не буде запускатися. Якщо виникла помилка, і абонент бажає викликати сторінку помилки, визначену у веб-програмі, її sendError
потрібно використовувати.
Я хотів би зазначити, що існує виняток (не тільки) для 404 за замовчуванням, який надає Spring. Докладніше див. У весняній документації . Тож якщо вам не потрібен власний виняток, ви можете просто зробити це:
@RequestMapping(value = "/**", method = RequestMethod.GET)
public ModelAndView show() throws NoSuchRequestHandlingMethodException {
if(something == null)
throw new NoSuchRequestHandlingMethodException("show", YourClass.class);
...
}
@PathVariable
з моєї точки зору не звертається із запитом. Чи вважаєте ви, що краще / чистіше використовувати власний виняток, позначений за допомогою @ResponseStatus(value = HttpStatus.NOT_FOUND)
?
З 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>
Сподіваюсь, що це допомагає.
Хоча позначена відповідь правильна, є спосіб досягти цього без винятків. Служба повертає 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);
}
}
Я рекомендую викинути HttpClientErrorException , як це
@RequestMapping(value = "/sample/")
public void sample() {
if (somethingIsWrong()) {
throw new HttpClientErrorException(HttpStatus.NOT_FOUND);
}
}
Ви повинні пам'ятати, що це можна зробити лише до того, як щось буде записано у вихідний потік сервлетів.
Whitelabel Error Page \n .... \n There was an unexpected error (type=Internal Server Error, status=500). \n 404 This is your not found error
Це трохи пізно, але якщо ви використовуєте 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)
HttpServletResponse#sendError(HttpServletResponse.SC_NOT_FOUND); return null;
з коду контролера. Тепер ззовні відповідь виглядає нічим не відрізняється від звичайного 404, який не потрапив на жоден контролер.
Налаштуйте 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);
}
}