使用spring @RestController在null上返回HTTP 204

use*_*576 23 java spring spring-mvc spring-restcontroller

这将返回200 OK,Content-Length:0

@RestController
public class RepoController {
    @RequestMapping(value = "/document/{id}", method = RequestMethod.GET)
    public Object getDocument(@PathVariable long id) {
       return null;
    }

}
Run Code Online (Sandbox Code Playgroud)

简单地说,我希望它返回204 No Content on null.

有没有办法强制spring-mvc/rest在null而不是200时返回204?我不想更改每个rest方法以返回ResponseEntity或类似的东西,只将null映射到204

spe*_*rum 41

您可以使用@ResponseStatus注释.这样您就可以使用void方法,而不必构建ResponseEntity.

@DeleteMapping(value = HERO_MAPPING)
@ResponseStatus(value = HttpStatus.NO_CONTENT)
public void delete(@PathVariable Long heroId) {
    heroService.delete(heroId);
}
Run Code Online (Sandbox Code Playgroud)

BTW在对象存在时返回200,否则在API REST设计上有点不寻常.当找不到请求的对象时,返回404(未找到)是很常见的.这可以使用ControllerAdvice实现.

在Spring REST中,最好使用Exception处理程序处理Exceptions,而不是使用逻辑来决定响应状态等.这是使用@ControllerAdvice批注的示例:http://www.jcombat.com/spring/exception-handling-在弹簧的RESTful的Web服务

  • 我认为OP希望成功返回200,如果他为空则返回204。您可以将任何所需的内容放入ResponseStatus。但是想法是为一个端点使用多个可能的HTTP代码。 (2认同)
  • @spekdrum当然是的.您应该使用异常处理程序来处理异常.但这不是OP所要求的.他希望在没有内容的情况下使用正确的响应返回200,并且在没有内容时返回204(这也是正确的响应)(如果您愿意,则返回null).OP甚至没有提到例外情况.在Java(Spring或其他)中,不应将异常用于流控制. (2认同)

Kar*_*k R 23

当然是的.

选项1 :

@RestController
public class RepoController {
    @RequestMapping(value = "/document/{id}", method = RequestMethod.GET)
    public Object getDocument(@PathVariable long id, HttpServletResponse response) {
       Object object = getObject();
       if( null == object ){
          response.setStatus( HttpStatus.SC_NO_CONTENT);
       }
       return object ;
    }
}
Run Code Online (Sandbox Code Playgroud)

选项2:

@RestController
public class RepoController {
    @RequestMapping(value = "/document/{id}", method = RequestMethod.GET)
    public Object getDocument(@PathVariable long id) {
       Object object = getObject();
       if ( null == object ){
          return new ResponseEntity<Void>(HttpStatus.NO_CONTENT);
       }

       return object ;
    }
}
Run Code Online (Sandbox Code Playgroud)

可能有拼写错误,但你得到的概念.

  • 可悲的是,这些选项都不是一个好的(干净的)解决方案.理想情况下,你的控制器方法会返回一个类型化的对象,而不是`Object`或`ResponseEntity`,并且会有某种截取器会注意到你返回null,并在那里设置`NO_CONTENT`状态代码(或者我只是被泽西和RESTEasy宠坏了). (4认同)

小智 10

我用过滤器解决了这个问题.它是全球性的,简单的.

package your.package.filter;

import org.springframework.http.HttpStatus;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class NoContentFilter extends OncePerRequestFilter {

    @Override
    protected void doFilterInternal(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, FilterChain filterChain) throws ServletException, IOException {
        filterChain.doFilter(httpServletRequest, httpServletResponse);
        if (httpServletResponse.getContentType() == null ||
                httpServletResponse.getContentType().equals("")) {
            httpServletResponse.setStatus(HttpStatus.NO_CONTENT.value());
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

并在您的web.xml中添加以下内容

<filter>
    <filter-name>restNoContentFilter</filter-name>
    <filter-class>your.package.filter.NoContentFilter</filter-class>
</filter>

<filter-mapping>
    <filter-name>restNoContentFilter</filter-name>
    <url-pattern>/rest/*</url-pattern>
</filter-mapping>
Run Code Online (Sandbox Code Playgroud)


Bil*_*BBB 5

你可以试试这个:

@RestController
public class RepoController {

    @RequestMapping(value = "/document/{id}", method = RequestMethod.GET)
    public ResponseEntity<String> getDocument(@PathVariable long id) {

       if(noError) {
           ............
           return new ResponseEntity<String>(HttpStatus.OK); 
       }
       else {
           return new ResponseEntity<String>(HttpStatus.BAD_REQUEST);
       }
   }
}
Run Code Online (Sandbox Code Playgroud)

您需要将 HttpStatus.BAD_REQUEST 更改为 204 代码状态的等效项