2015-09-04 4 views
11

Это возвращает 200 OK с Content-Length: 0Возвращение HTTP 204 на нуль с пружинным @RestController

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

} 

Проще говоря, я хотел бы его вернуть 204 No Content на нуль.

Есть ли способ заставить spring-mvc/rest возвращать 204 по нулевому значению не 200? Я не хочу менять каждый метод отдыха, чтобы возвращать ResponseEntity или что-то в этом роде, только от map null до 204

ответ

15

Конечно, да.

Вариант 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 ; 
    } 
} 

Вариант 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 ; 
    } 
} 

Может иметь опечаток, но вы получите эту концепцию.

+0

Вариант 2 работал для меня. Хорошее решение! –

2

Вы можете попробовать это:

@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); 
     } 
    } 
} 

Uou необходимо изменить HttpStatus.BAD_REQUEST с эквивалентом для состояния 204 кода

19

Вы можете использовать @ResponseStatus аннотацию. Таким образом, у вас может быть метод void, и вам не нужно создавать ResponseEntity.

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

Обновление: Из-за некоторые комментарии к этой реакции я ее уточнению. В Spring REST лучше обрабатывать исключения с помощью обработчика исключений вместо того, чтобы вводить логику для определения статуса ответа и т. Д. Это пример, использующий аннотацию @ControllerAdvice: http://www.jcombat.com/spring/exception-handling-in-spring-restful-web-service

Из-за этого я считаю, что это хорошее решение.

+1

Я думаю, что OP хотел вернуть 200 на успех, и 204, если у него было null. Вы можете поместить все, что захотите, в ResponseStatus. Но идея заключалась в том, чтобы иметь несколько возможных HTTP-кодов для одной конечной точки. –

+0

Я согласен с @ Jean-FrançoisBeauchef. Это неправильная обработка. Этот статус ответа применяется независимо от результата (исключая сценарий исключения). Вопроситель хотел знать, как удовлетворять условию «null» –

+0

Извините, но я не согласен. При использовании Spring REST лучше обрабатывать исключения и коды ответов с помощью обработчика исключений. Это пример http://www.jcombat.com/spring/exception-handling-in-spring-restful-web-service – spekdrum

0

Тот же ответ, но решил АОП:

@Aspect 
public class NoContent204HandlerAspect { 

    @Pointcut("execution(public * xx.xxxx.controllers.*.*(..))") 
    private void anyControllerMethod() { 
    } 

    @Around("anyControllerMethod()") 
    public Object handleException(ProceedingJoinPoint joinPoint) throws Throwable { 

    Object[] args = joinPoint.getArgs(); 

    Optional<HttpServletResponse> response = Arrays.asList(args).stream().filter(x -> x instanceof HttpServletResponse).map(x -> (HttpServletResponse)x).findFirst(); 

    if (!response.isPresent()) 
     return joinPoint.proceed(); 

    Object retVal = joinPoint.proceed(); 
    if (retVal == null) 
     response.get().setStatus(HttpStatus.NO_CONTENT.value()); 

    return retVal; 
    } 
} 
+0

Можете ли вы предоставить более подробную информацию о том, что на самом деле происходит здесь. Я пытаюсь реализовать аналогичное решение. Моя идея состоит в том, чтобы автоматически возвращать 204 для всех методов, которые имеют тип возврата void. Похоже, это решение требует, чтобы метод принимал HttpServletResponse как вход. Я бы хотел этого избежать. –

+0

Попробуйте использовать статический способ для получения HttpServletResponse, например [здесь] (https://stackoverflow.com/questions/20531204/why-there-is-not-a-holder-class-for-response-like-requestcontextholder) Остальные должны быть одинаковыми, но @Pointcut должен охватывать только недействительные методы. –

8

Я решил эту проблему с помощью фильтра. Это глобально и просто.

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()); 
     } 
    } 
} 

и добавьте следующее в вашем 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> 
+1

(HttpStatus.NO_CONTENT.value()) Я скопировал рабочее решение +1 голос –

+1

Очень приятное решение – Stephan

 Смежные вопросы

  • Нет связанных вопросов^_^