如何从弹簧控制器返回未找到状态

Posted

技术标签:

【中文标题】如何从弹簧控制器返回未找到状态【英文标题】:how to return not found status from spring controller 【发布时间】:2014-04-27 11:31:49 【问题描述】:

我有以下spring控制器代码,如果在数据库中找不到用户,想返回未找到状态,怎么办?

@Controller
public class UserController 
  @RequestMapping(value = "/user?$id", method = RequestMethod.GET)
  public @ResponseBody User getUser(@PathVariable Long id) 
    ....
  

【问题讨论】:

【参考方案1】:

有了最新的更新,你就可以使用了

return ResponseEntity.of(Optional<user>);

其余的由下面的代码处理

    /**
     * A shortcut for creating a @code ResponseEntity with the given body
     * and the @linkplain HttpStatus#OK OK status, or an empty body and a
     * @linkplain HttpStatus#NOT_FOUND NOT FOUND status in case of a
     * @linkplain Optional#empty() parameter.
     * @return the created @code ResponseEntity
     * @since 5.1
     */
    public static <T> ResponseEntity<T> of(Optional<T> body) 
        Assert.notNull(body, "Body must not be null");
        return body.map(ResponseEntity::ok).orElse(notFound().build());
    

【讨论】:

【参考方案2】:

public static ResponseEntity of(可选正文)

在 Optional.empty() 参数的情况下创建具有给定正文和 OK 状态的 ResponseEntity 或空正文和 NOT FOUND 状态的快捷方式。

@GetMapping(value = "/user/id")
public ResponseEntity<User> getUser(@PathVariable final Long id) 
    return ResponseEntity.of(userRepository.findOne(id)));


public Optional<User> findOne(final Long id) 
    MapSqlParameterSource paramSource = new MapSqlParameterSource().addValue("id", id);
    try 
        return Optional.of(namedParameterJdbcTemplate.queryForObject(SELECT_USER_BY_ID, paramSource, new UserMapper()));
     catch (DataAccessException dae) 
        return Optional.empty();
    

【讨论】:

【参考方案3】:

需要使用 ResponseEntity 或 @ResponseStatus,或使用“extends RuntimeException”

@DeleteMapping(value = "")
    public ResponseEntity<Employee> deleteEmployeeById(@RequestBody Employee employee) 

        Employee tmp = employeeService.deleteEmployeeById(employee);

        return new ResponseEntity<>(tmp, Objects.nonNull(tmp) ? HttpStatus.OK : HttpStatus.NOT_FOUND);
    

@ResponseStatus(value=HttpStatus.NOT_FOUND, reason="was Not Found")

【讨论】:

【参考方案4】:

将您的处理程序方法更改为具有ResponseEntity 的返回类型。然后你可以适当地返回

@RequestMapping(value = "/user/id", method = RequestMethod.GET)
public ResponseEntity<User> getUser(@PathVariable Long id) 
    User user = ...;
    if (user != null) 
        return new ResponseEntity<User>(user, HttpStatus.OK);
    
    return new ResponseEntity<>(HttpStatus.NOT_FOUND);

Spring 将使用与 @ResponseBody 相同的 HttpMessageConverter 对象来转换 User 对象,但现在您可以更好地控制要在响应中返回的状态代码和标头。

【讨论】:

【参考方案5】:

使用方法引用运算符::可以更短

@RequestMapping(value = "/user/id", method = RequestMethod.GET)
public ResponseEntity<User> getUser(@PathVariable Long id) 
   return Optional.ofNullable(userRepository.findOne(id))
        .map(ResponseEntity::ok)
        .orElse(ResponseEntity.notFound().build());

【讨论】:

【参考方案6】:

JDK8 方法:

@RequestMapping(value = "/user/id", method = RequestMethod.GET)
public ResponseEntity<User> getUser(@PathVariable Long id) 
    return Optional
            .ofNullable( userRepository.findOne(id) )
            .map( user -> ResponseEntity.ok().body(user) )          //200 OK
            .orElseGet( () -> ResponseEntity.notFound().build() );  //404 Not found

【讨论】:

ResponseEntity.notFound().build() 导致以下警告(SpringWeb 4.3.1):Bad return type in lambda expression: ResponseEntity&lt;Void&gt; cannot be converted to ResponseEntity&lt;User&gt;

以上是关于如何从弹簧控制器返回未找到状态的主要内容,如果未能解决你的问题,请参考以下文章

弹簧休息控制器不适用于文件上传

如何从控制器调用身份验证 - 弹簧安全核心插件

当从控制器启动的作业失败时,如何防止弹簧批处理关闭应用程序?

弹簧休息控制器不返回html

从 Web Api 控制器返回 http 状态码

服务器以 403 (Forbidden) 状态响应