我目前正在使用Spring MVC和Hibernate来开发我的网络应用程序。还在学习java的内部工作原理。
我发现自己需要将数据存储在可以接受不同类型的对象以及其他一些数据字段的字段中。更确切地说,我想创建一个可以保存消息,错误代码等的ReturnObject。这样我的返回JSON可以通过api保持一致。
这就是我创建ReturnObject的方法
public class ReturnResponse {
//Set fields
private Object returnObj; <----- Need this to accept different types
private HttpStatus httpStatus;
private String message;
private String developerMessage;
// Start build
public ReturnResponse(){
this.returnObj = returnObj;
this.httpStatus =.....etc.
}
// Setters... getters...
}
private Object returnObj;
这样这个字段可以接受Collection,Maps,Class..etc但是这样安全吗?
我似乎记得在字段中声明特定对象类型以确保类型安全始终是一个好习惯。
问题
您是否在将来看到可预见的问题,是否有更好的方法可以做到这一点?
如果这不是类型安全的,我将如何使其更安全。
答案 0 :(得分:2)
您可以使用通用:
public class ReturnResponse<ObjectType> {
private ObjectType returnObj;
private HttpStatus httpStatus;
private String message;
private String developerMessage;
public ReturnResponse(ObjectType returnObj, /*other parameters...*/) {
this.returnObj = returnObj;
// set other parameters
}
public ObjectType getReturnObj() {
return this.returnObj;
}
// ...
}
如果您知道何时将ReturnResponse
实例化为返回对象的类型,它将会起作用。
我在大多数API中使用这种模式没有问题。
答案 1 :(得分:1)
如果您希望&#34;将数据存储在可以接受不同类型的对象以及其他一些数据字符串的字段中。那么您需要有一个基类对于那个在你的情况下可能是对象的对象。
问题是你需要有一些方法可以在以后的代码中解密,这是什么类型的对象 - 在大多数情况下我认为这是不合需要的,并且需要不安全的转换。
我能想到的更安全的方法就是制作一些包装材料:
public class Bean {
private String string;
private Integer integer;
private List<String> list;
private Bicycle bicycle;
//setters
//...
public Optional<Bicycle> getBicycle() {
return Optional.ofNullable(bicycle);
}
//... and so on...
}
答案 2 :(得分:1)
错误处理程序应该在控制器中,它应该响应http错误。这意味着正确的HTTP错误状态和所需的错误消息。错误不应该看起来像一个成功的请求(无状态代码200)。这是一个错误。在您的前端,您应该相应地处理http错误响应。
使用弹簧,这可以很容易地完成。这是我的项目的错误处理程序的示例。它是一个带有注释@ControllerAdvice
的自有类。 spring会自动使用它。
此类将自动捕获使用@ExceptionHandler
定义的任何未处理的异常,并在我的情况下发送ShortExceptionResponse
,其中包含抛出的异常的类型和消息,并定义了正确的Http错误状态与@ResponseStatus
。
在前端,您可以根据不同的HTTP状态错误代码做出相应的反应。它很好而且通用。
@ControllerAdvice
public class RestExceptionResponseHandler {
private static final Logger LOGGER = LoggerFactory.getLogger(SetRestController.class);
@ExceptionHandler(NoSuchElementException.class)
@ResponseStatus(HttpStatus.NOT_FOUND)
public @ResponseBody
ShortExceptionResponse noSuchElementExceptionHandler(Exception ex) {
LOGGER.error("An error occured processing a rest request", ex);
return new ShortExceptionResponse(ex);
}
@ExceptionHandler(value = {EntityAlreadyExistsException.class})
@ResponseStatus(HttpStatus.FORBIDDEN)
public @ResponseBody
ShortExceptionResponse entityAlreadyExistsExceptionHandler(EntityAlreadyExistsException ex) {
LOGGER.debug("A rest request could not been process due an illegal state of the target entity", ex);
return new ShortExceptionResponse(ex);
}
@ExceptionHandler(value = {IllegalArgumentException.class, UnsupportedOperationException.class})
@ResponseStatus(HttpStatus.BAD_REQUEST)
public @ResponseBody
ShortExceptionResponse illegalArgumentExceptionHandler(Exception ex) {
LOGGER.error("An error occured processing a rest request", ex);
return new ShortExceptionResponse(ex);
}
@ExceptionHandler(value = {HttpMessageNotReadableException.class})
@ResponseStatus(HttpStatus.BAD_REQUEST)
public @ResponseBody
ShortExceptionResponse httpMessageNotReadableExceptionHandler(Exception ex) {
LOGGER.error("An error occured processing a rest request", ex);
if (ex.getCause() instanceof InvalidFormatException) {
return new ShortExceptionResponse(new InvalidValueException(((InvalidFormatException) ex.getCause()).getOriginalMessage()));
}
return new ShortExceptionResponse(ex);
}
...
...
}
在实际的控制器中,你只是继续抛出异常,它将由你的错误处理程序处理
@RequestMapping(method = RequestMethod.POST)
public @ResponseBody
MetadataDTO createMetadata(@RequestBody MetadataDTO metaDataDTO) throws EntityAlreadyExistsException {
MetadataDTO result = metaDataService.createMetadata(metaDataDTO.getName(), metaDataDTO.getDescription(), metaDataDTO.getType());
return result;
}
答案 3 :(得分:0)
您可以创建一个“模型”类来存储要转换为json的完整对象:
@AllArgsConstructor //or make a constructor with all the fields manually
class ResponseObject {
User user;
House house;
Car car;
}
由于您使用的是Spring,因此您已经有了Jackson库。因此,您可以这样做:
@Autowired ObjectMapper objectMapper; // no need to configure anything to use this
public String getJson(){
User user = new User("user", "password");
House house = new House(4, true, ...);
Car car = new Car();
ResponseObject resp = new ResponseObject(user, house, car);
String json = null;
json = objectMapper.convertValue(resp, ResponseObject.class);
// or:
try {
json = objectMapper.writeValueAsString(resp);
} catch (Exception e) {
...
}
// or: (would need to use a google Gson dependency)
Gson gson = new Gson();
json = gson.toJson(resp, ResponseObject.class);
return json;
}
或者,如果您确实需要灵活性,
@Autowired ObjectMapper mapper;
public void printJson() {
Map<String, Object> jsonMap = new HashMap<>();
jsonMap.put("number", 5);
jsonMap.put("String", "string");
jsonMap.put("kanky", 987L);
String json = mapper.writeValueAsString(jsonMap);
System.out.println("json: " + json);
} // works fine if your map values have a toString defined