英文:
Spring Boot Controller return generic types (A or B)
问题
您的控制器函数中使用的ResponseMessage<?>
中的问号?
并不是最好的方式,您可以使用Java的通配符<? extends T>
来更好地表示返回值,其中T
是ResponseMessage
的类型参数。这将更准确地表明您的函数可能返回不同类型的ResponseMessage
。这是一个更新后的示例:
public ResponseMessage<? extends Object> findRecent(@AuthenticationPrincipal LoginUser user) {
Optional<TodoResponse> todo = todoService.findRecent(user.getId());
return todo.isPresent() ? ResponseMessage.ok(todo.get()) : ResponseMessage.noContent();
}
在这种情况下,您的findRecent
函数可以返回ResponseMessage<TodoResponse>
或ResponseMessage<String>
,具体取决于todoService.findRecent
的返回值。这种方式更具灵活性,同时仍然提供了类型安全。
英文:
I develop simple todo-list application with spring boot. And I wanna send common response dto from all request. The data filed in ReponseMessage is Generic because it can be various type.
public class ResponseMessage<T> {
private int statusCode = HttpStatus.OK.value();
private String message = "";
protected T data; // this is generic. it can be many response dto.
public static ResponseMessage<String> ok() {
return new ResponseMessage<>("");
}
public static <T> ResponseMessage<T> ok(T data) {
return new ResponseMessage<>(data);
}
public static ResponseMessage<Object> noContent() {
return new ResponseMessage<>(HttpStatus.NO_CONTENT.value(), HttpStatus.NO_CONTENT.getReasonPhrase(), "");
}
protected ResponseMessage(T data) {
this.data = data;
}
private ResponseMessage(int statusCode, String message, T data) {
this.statusCode = statusCode;
this.message = message;
this.data = data;
}
protected ResponseMessage() {}
public int getStatusCode() {
return statusCode;
}
public String getMessage() {
return message;
}
public T getData() {
return data;
}
}
Now i need to make a feature that find a recend todo.
If todo exists, send ResponseMessage<TodoResponse>.
{
"statusCode": 200,
"message": "",
"data": [
{
"id": 1,
"title": "test",
"status": "TODO"
}
]
}
If todo doesn't exist, send ResponseMessage<Srring>.
{
"statusCode": 200,
"message": "",
"data": []
}
Now my controller function return like this.
public ResponseMessage<?> findRecent(@AuthenticationPrincipal LoginUser user) {
Optional<TodoResponse> todo = todoService.findRecent(user.getId());
return todo.isPresent() ? ResponseMessage.ok(todo.get()) : ResponseMessage.noContent();
}
I know that the question mark '?' is not good. so what is better way to return A or B in this case? plz help me.
答案1
得分: 1
如果将noContent().data
设置为null,您可以安全地分配任何类型:
public static <T> ResponseMessage<T> noContent() {
return new ResponseMessage<>(HttpStatus.NO_CONTENT.value(), HttpStatus.NO_CONTENT.getReasonPhrase(), null);
}
另外,请注意调用Optional.isPresent()
然后再调用get()
有点类似反模式。在您的情况下,您可以简化为:
return todoService.findRecent(user.getId())
.map(ResponseMessage::ok)
.orElseGet(ResponseMessage::noContent);
英文:
If you set noContent().data
to null, you can safely assign it any type:
public static <T> ResponseMessage<T> noContent() {
return new ResponseMessage<>(HttpStatus.NO_CONTENT.value(), HttpStatus.NO_CONTENT.getReasonPhrase(), null);
}
Also note that calling Optional.isPresent()
and then get()
is something of an antipattern. In your case, you can simplify it to this:
return todoService.findRecent(user.getId())
.map(ResponseMessage::ok)
.orElseGet(ResponseMessage::noContent);
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论