我使用Spring MVC 4(或Spring-Boot)编写了简单的rest应用程序。在控制器中,我返回ResponseEntity
。但在某些情况下,我想给JSON成功,如果有验证错误,我想给出错误JSON。目前成功和错误响应完全不同,所以我创建了2个错误和成功的类。如果内部逻辑正常,我想在控制器内返回ResponseEntity<Success>
。否则我想返回ResponseEntity<Error>
。有没有办法做到这一点。
Success
和Error
是我用来表示成功和错误响应的两个类。
答案 0 :(得分:38)
我建议使用Spring的@ControllerAdvice
来处理验证错误。阅读this guide以获得一个很好的介绍,从名为&#34; Spring Boot Error Handling&#34;的部分开始。对于深入讨论,Spring.io博客中的an article已于2018年4月更新。
关于其工作原理的简要总结:
ResponseEntity<Success>
。它不会对返回错误或异常响应负责。@ControllerAdvice
@ExceptionHandler
ResponseEntity<Error>
使用这种方法,您只需要在一个位置为API中的所有端点实现控制器异常处理。它还使您的API可以轻松地在所有端点上具有统一的异常响应结构。这简化了客户的异常处理。
答案 1 :(得分:29)
您可以在同一请求映射方法上返回通用通配符<?>
以返回Success
和Error
public ResponseEntity<?> method() {
boolean b = // some logic
if (b)
return new ResponseEntity<Success>(HttpStatus.OK);
else
return new ResponseEntity<Error>(HttpStatus.CONFLICT); //appropriate error code
}
@Mark诺曼答案是正确的方法
答案 2 :(得分:5)
我不确定但是,我认为您可以使用@ResponseEntity
和@ResponseBody
并发送2个不同的成功,其次是错误消息,如:
@RequestMapping(value ="/book2", produces =MediaType.APPLICATION_JSON_VALUE )
@ResponseBody
Book bookInfo2() {
Book book = new Book();
book.setBookName("Ramcharitmanas");
book.setWriter("TulasiDas");
return book;
}
@RequestMapping(value ="/book3", produces =MediaType.APPLICATION_JSON_VALUE )
public ResponseEntity<Book> bookInfo3() {
Book book = new Book();
book.setBookName("Ramayan");
book.setWriter("Valmiki");
return ResponseEntity.accepted().body(book);
}
有关详细信息,请参阅: http://www.concretepage.com/spring-4/spring-4-mvc-jsonp-example-with-rest-responsebody-responseentity
答案 3 :(得分:3)
可以在不使用泛型的情况下返回ResponseEntity
,如下所示,
public ResponseEntity method() {
boolean isValid = // some logic
if (isValid){
return new ResponseEntity(new Success(), HttpStatus.OK);
}
else{
return new ResponseEntity(new Error(), HttpStatus.BAD_REQUEST);
}
}
答案 4 :(得分:3)
您可以将地图与您的对象或字符串一起使用,如下所示:
@RequestMapping(value = "/path",
method = RequestMethod.GET,
produces = MediaType.APPLICATION_JSON_VALUE)
@ResponseBody
public ResponseEntity<Map<String,String>> getData(){
Map<String,String> response = new HashMap<String, String>();
boolean isValid = // some logic
if (isValid){
response.put("ok", "success saving data");
return ResponseEntity.accepted().body(response);
}
else{
response.put("error", "an error expected on processing file");
return ResponseEntity.badRequest().body(response);
}
}
答案 5 :(得分:2)
这是我会这样做的方式:
public ResponseEntity < ? extends BaseResponse > message(@PathVariable String player) { //REST Endpoint.
try {
Integer.parseInt(player);
return new ResponseEntity < ErrorResponse > (new ErrorResponse("111", "player is not found"), HttpStatus.BAD_REQUEST);
} catch (Exception e) {
}
Message msg = new Message(player, "Hello " + player);
return new ResponseEntity < Message > (msg, HttpStatus.OK);
}
@RequestMapping(value = "/getAll/{player}", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity < List < ? extends BaseResponse >> messageAll(@PathVariable String player) { //REST Endpoint.
try {
Integer.parseInt(player);
List < ErrorResponse > errs = new ArrayList < ErrorResponse > ();
errs.add(new ErrorResponse("111", "player is not found"));
return new ResponseEntity < List < ? extends BaseResponse >> (errs, HttpStatus.BAD_REQUEST);
} catch (Exception e) {
}
Message msg = new Message(player, "Hello " + player);
List < Message > msgList = new ArrayList < Message > ();
msgList.add(msg);
return new ResponseEntity < List < ? extends BaseResponse >> (msgList, HttpStatus.OK);
}
答案 6 :(得分:1)
您也可以像这样实现在同一个请求映射方法上返回Success和Error,使用Object类(java中每个类的Parent类): -
public ResponseEntity< Object> method() {
boolean b = // logic here
if (b)
return new ResponseEntity< Object>(HttpStatus.OK);
else
return new ResponseEntity< Object>(HttpStatus.CONFLICT); //appropriate error code
}
答案 7 :(得分:0)
我过去常常使用这样的课程。当消息中设置错误消息时出现错误,设置 statusCode 。数据在适当的时候存储在Map或List中。
/**
*
*/
package com.test.presentation.response;
import java.util.Collection;
import java.util.Map;
/**
* A simple POJO to send JSON response to ajax requests. This POJO enables us to
* send messages and error codes with the actual objects in the application.
*
*
*/
@SuppressWarnings("rawtypes")
public class GenericResponse {
/**
* An array that contains the actual objects
*/
private Collection rows;
/**
* An Map that contains the actual objects
*/
private Map mapData;
/**
* A String containing error code. Set to 1 if there is an error
*/
private int statusCode = 0;
/**
* A String containing error message.
*/
private String message;
/**
* An array that contains the actual objects
*
* @return the rows
*/
public Collection getRows() {
return rows;
}
/**
* An array that contains the actual objects
*
* @param rows
* the rows to set
*/
public void setRows(Collection rows) {
this.rows = rows;
}
/**
* An Map that contains the actual objects
*
* @return the mapData
*/
public Map getMapData() {
return mapData;
}
/**
* An Map that contains the actual objects
*
* @param mapData
* the mapData to set
*/
public void setMapData(Map mapData) {
this.mapData = mapData;
}
/**
* A String containing error code.
*
* @return the errorCode
*/
public int getStatusCode() {
return statusCode;
}
/**
* A String containing error code.
*
* @param errorCode
* the errorCode to set
*/
public void setStatusCode(int errorCode) {
this.statusCode = errorCode;
}
/**
* A String containing error message.
*
* @return the errorMessage
*/
public String getMessage() {
return message;
}
/**
* A String containing error message.
*
* @param errorMessage
* the errorMessage to set
*/
public void setMessage(String errorMessage) {
this.message = errorMessage;
}
}
希望这有帮助。
答案 8 :(得分:0)
注意:如果您从Spring Boot 1升级到Spring Boot 2,则会有一个ResponseStatusException
,其中包含Http错误代码和说明。
因此,您可以按预期方式有效地使用泛型。
对我来说唯一具有挑战性的情况是状态204的响应类型(没有主体)。我倾向于将这些方法标记为ResponseEntity<?>
,因为ResponseEntity<Void>
的预测性较低。
答案 9 :(得分:0)
Spring 2引入了 ResponseStatusException ,您可以在同一时间 返回字符串,不同的HTTP状态代码,DTO。
@PostMapping("/save")
public ResponseEntity<UserDto> saveUser(@RequestBody UserDto userDto) {
if(userDto.getId() != null) {
throw new ResponseStatusException(HttpStatus.NOT_ACCEPTABLE,"A new user cannot already have an ID");
}
return ResponseEntity.ok(userService.saveUser(userDto));
}
答案 10 :(得分:0)
使用自定义异常类,您可以返回不同的HTTP状态代码和dto对象。
@PostMapping("/save")
public ResponseEntity<UserDto> saveUser(@RequestBody UserDto userDto) {
if(userDto.getId() != null) {
throw new UserNotFoundException("A new user cannot already have an ID");
}
return ResponseEntity.ok(userService.saveUser(userDto));
}
异常类
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ResponseStatus;
@ResponseStatus(value = HttpStatus.NOT_FOUND, reason = "user not found")
public class UserNotFoundException extends RuntimeException {
public UserNotFoundException(String message) {
super(message);
}
}
答案 11 :(得分:0)
在特殊情况下,我建议您在应用程序中采用RFC-7807 Problem Details for HTTP APIs 标准。
Zalando's Problems for Spring提供了与Spring Boot的良好集成,您可以轻松地将其与现有的基于Spring Boot的应用程序集成。就像JHipster一样。
在您的应用程序中采用RFC-7087之后,只需在控制器方法中抛出Exception,您将获得详细的标准错误响应,例如:
{
"type": "https://example.com/probs/validation-error",
"title": "Request parameter is malformed.",
"status": 400
"detail": "Validation error, value of xxx should be a positive number.",
"instance": "/account/12345/msgs/abc",
}