Answers:
从Spring 3.0开始,您还可以抛出带有@ResponseStatus
注释声明的Exception :
@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()
用空的实现覆盖。
从Spring 5.0开始,您不必创建其他异常:
throw new ResponseStatusException(NOT_FOUND, "Unable to find resource");
另外,您可以使用一个内置的例外情况涵盖多种情况,并且您拥有更多的控制权。
看更多:
重写您的方法签名,使其接受HttpServletResponse
为参数,以便您可以对其进行调用setStatus(int)
。
setStatus(int)
javadoc声明如下:如果使用此方法设置错误代码,则不会触发容器的错误页面机制。如果存在错误,并且调用者希望调用Web应用程序中定义的错误页面,则sendError
必须改用它。
我要提到的是,Spring默认提供(默认)404的一个例外。有关详细信息,请参见Spring文档。因此,如果您不需要自己的异常,则可以执行以下操作:
@RequestMapping(value = "/**", method = RequestMethod.GET)
public ModelAndView show() throws NoSuchRequestHandlingMethodException {
if(something == null)
throw new NoSuchRequestHandlingMethodException("show", YourClass.class);
...
}
@PathVariable
我的观点,当实体不存在时,就没有请求处理。您是否认为使用带有注释的Exception更好/更清洁@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处理您的Exceptions,@ControllerAdvice注释类的默认行为将协助所有已知的Controller。
因此,当您有任何Controller抛出404错误时,它将被调用。
像下面这样:
@ControllerAdvice
class GlobalControllerExceptionHandler {
@ResponseStatus(HttpStatus.NOT_FOUND) // 404
@ExceptionHandler(Exception.class)
public void handleNoTFound() {
// Nothing to do
}
}
并在web.xml中映射此404响应错误,如下所示:
<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);
}
}
您必须记住,只有在将任何内容写入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
这有点晚了,但是如果您正在使用Spring Data REST,那么已经有org.springframework.data.rest.webmvc.ResourceNotFoundException
它也使用@ResponseStatus
注释了。不再需要创建自定义运行时异常。
只需使用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);
}
}