如何让Spring 3.0控制器触发404?
我有一个@RequestMapping(value = "/**", method = RequestMethod.GET)
的控制器,而某些URLs访问控制器,我希望容器能够提供404.
答案 0 :(得分:298)
从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();
}
}
}
答案 1 :(得分:36)
重写您的方法签名,使其接受HttpServletResponse
作为参数,以便您可以在其上调用setStatus(int)
。
答案 2 :(得分:24)
我想提一下,Spring提供的默认值为404(不仅仅是)。有关详细信息,请参阅Spring documentation。因此,如果您不需要自己的例外,您可以这样做:
@RequestMapping(value = "/**", method = RequestMethod.GET)
public ModelAndView show() throws NoSuchRequestHandlingMethodException {
if(something == null)
throw new NoSuchRequestHandlingMethodException("show", YourClass.class);
...
}
答案 3 :(得分:21)
自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&lt; T&gt;比@ResponseBody注释更灵活 - 请参阅another question)
答案 4 :(得分:14)
您可以使用@ControllerAdvice来处理您的例外, @ControllerAdvice带注释的类的默认行为将协助所有已知的控制器。
所以当任何控制器抛出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>
希望有助于。
答案 5 :(得分:9)
如果您的控制器方法适用于文件处理,那么ResponseEntity
非常方便:
@Controller
public class SomeController {
@RequestMapping.....
public ResponseEntity handleCall() {
if (isFound()) {
return new ResponseEntity(...);
}
else {
return new ResponseEntity(404);
}
}
}
答案 6 :(得分:6)
我建议抛出 HttpClientErrorException ,就像这样
@RequestMapping(value = "/sample/")
public void sample() {
if (somethingIsWrong()) {
throw new HttpClientErrorException(HttpStatus.NOT_FOUND);
}
}
您必须记住,只有在将任何内容写入servlet输出流之前,才能执行此操作。
答案 7 :(得分:6)
虽然明确的答案是正确的,但有一种方法可以毫无例外地实现这一点。该服务返回搜索对象的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);
}
}
答案 8 :(得分:3)
从Spring 5.0开始,您不必创建其他异常:
throw new ResponseStatusException(NOT_FOUND, "Unable to find resource");
此外,您可以使用一个内置的例外情况涵盖多种情况,并且您拥有更多的控制权。
查看更多:
答案 9 :(得分:2)
这有点晚了,但如果您使用的是Spring Data REST,那么已经org.springframework.data.rest.webmvc.ResourceNotFoundException
它还使用@ResponseStatus
注释。无需再创建自定义运行时异常。
答案 10 :(得分:1)
此外,如果您想从控制器返回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错误。
答案 11 :(得分:0)
只需使用web.xml添加错误代码和404错误页面即可。但请确保404错误页面不能位于WEB-INF下。
<error-page>
<error-code>404</error-code>
<location>/404.html</location>
</error-page>
这是最简单的方法,但这有一些限制。假设您要为添加了其他页面的页面添加相同的样式。这样你就不能那样了。您必须使用@ResponseStatus(value = HttpStatus.NOT_FOUND)
答案 12 :(得分:0)
使用设置
配置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;
}
}
答案 13 :(得分:0)
因为总是有至少十种做同一件事的方式总是很好的:
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);
}
}