gpt4 book ai didi

java - 如何包装来自 Spring REST 存储库的 JSON 响应?

转载 作者:搜寻专家 更新时间:2023-10-31 20:32:32 25 4
gpt4 key购买 nike

我有一个 spring REST Controller ,它返回以下 JSON 负载:

[
{
"id": 5920,
"title": "a title"
},
{
"id": 5926,
"title": "another title",
}
]

REST Controller 及其相应的 get 请求方法:

@RequestMapping(value = "example")
public Iterable<Souvenir> souvenirs(@PathVariable("user") String user) {
return new souvenirRepository.findByUserUsernameOrderById(user);
}

现在 Souvenir 类是一个 pojo:

@Entity
@Data
public class Souvenir {

@Id
@GeneratedValue
private long id;

private String title;

private Date date;
}

关于 https://www.owasp.org/index.php/OWASP_AJAX_Security_Guidelines#Always_return_JSON_with_an_Object_on_the_outsidehttp://haacked.com/archive/2009/06/25/json-hijacking.aspx/我想将响应包装在一个对象中,这样它就不容易受到攻击。当然我可以这样做:

@RequestMapping(value = "example")
public SouvenirWrapper souvenirs(@PathVariable("user") String user) {
return new SouvenirWrapper(souvenirRepository.findByUserUsernameOrderById(user));
}

@Data
class SouvenirWrapper {
private final List<Souvenir> souvenirs;

public SouvenirWrapper(List<Souvenir> souvenirs) {
this.souvenirs = souvenirs;
}
}

这会产生以下 JSON 负载:

   {
"souvenirs": [
{
"id": 5920,
"title": "a title"
},
{
"id": 5926,
"title": "another title",
}
]
}

这有助于防止某些 JSON/Javascript 攻击,但我不喜欢 Wrapper 类的冗长。我当然可以用泛型概括上述方法。是否有另一种方法可以在 Spring 生态系统中实现相同的结果(使用注释或类似的东西)?一个想法是该行为由 Spring 自动完成,因此只要有一个返回对象列表的 REST Controller ,它就可以将这些对象包装在一个对象包装器中,这样就不会序列化直接的对象列表?

最佳答案

我最终得到了以下解决方案(感谢@vadim-kirilchuk):

我的 Controller 看起来和以前一模一样:

@RequestMapping(value = "example")
public Iterable<Souvenir> souvenirs(@PathVariable("user") String user) {
return new souvenirRepository.findByUserUsernameOrderById(user);
}

我添加了以下 ResponseBodyAdvice 的实现当引用包中的 Controller 尝试响应客户端调用时,它基本上会被执行(据我所知):

@ControllerAdvice(basePackages = "package.where.all.my.controllers.are")
public class JSONResponseWrapper implements ResponseBodyAdvice {
@Override
public boolean supports(MethodParameter returnType, Class converterType) {
return true;
}

@Override
@SuppressWarnings("unchecked")
public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {
if (body instanceof List) {
return new Wrapper<>((List<Object>) body);
}
return body;
}

@Data // just the lombok annotation which provides getter and setter
private class Wrapper<T> {
private final List<T> list;

public Wrapper(List<T> list) {
this.list = list;
}
}
}

因此,通过这种方法,我可以将我现有的方法签名保留在我的 Controller ( public Iterable<Souvenir> souvenirs(@PathVariable("user") String user) ) 中,并且 future 的 Controller 不必担心将其 Iterables 包装在这样的包装器中,因为框架完成了这部分工作。

关于java - 如何包装来自 Spring REST 存储库的 JSON 响应?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40323299/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com