gpt4 book ai didi

java - Spring MVC : How to modify json response sent from controller

转载 作者:IT老高 更新时间:2023-10-28 13:50:27 27 4
gpt4 key购买 nike

我已经用这样的 Controller 构建了一个 json REST 服务:

@Controller
@RequestMapping(value = "/scripts")
public class ScriptController {

@Autowired
private ScriptService scriptService;

@RequestMapping(method = RequestMethod.GET)
@ResponseBody
public List<Script> get() {
return scriptService.getScripts();
}
}

它工作正常,但现在我需要修改所有响应并向所有响应添加“状态”和“消息”字段。我已经阅读了一些解决方案:

  1. 从某个特定类的所有 Controller 方法对象返回,例如,RestResponse,将包含“状态”和“消息”字段(但它是不是通用解决方案,因为我将不得不修改我所有的 Controller 并以新的风格编写新的 Controller )
  2. 使用切面拦截所有 Controller 方法(但在这种情况下我无法更改返回类型)

如果我想将从 Controller 方法返回的值包装到类的对象中,您能否提出一些其他通用且正确的解决方案:

public class RestResponse {

private int status;
private String message;
private Object data;

public RestResponse(int status, String message, Object data) {
this.status = status;
this.message = message;
this.data = data;
}

//getters and setters
}

最佳答案

我也遇到过类似的问题,建议你使用 Servlet Filters 来解决。

Servlet 过滤器是 Java 类,可在 Servlet 编程中用于在客户端访问后端资源之前拦截来自客户端的请求,或者在将来自服务器的响应发送回客户端之前对其进行操作。

您的过滤器必须实现 javax.servlet.Filter 接口(interface)并覆盖三个方法:

public void doFilter (ServletRequest, ServletResponse, FilterChain)

由于客户端请求链末端的资源,每次请求/响应对通过链时都会调用此方法。

public void init(FilterConfig filterConfig)

在过滤器投入使用之前调用,并设置过滤器的配置对象。

public void destroy()

在过滤器停止服务后调用。

可以使用任意数量的过滤器,执行顺序与 web.xml 中定义的顺序相同。

web.xml:

...
<filter>
<filter-name>restResponseFilter</filter-name>
<filter-class>
com.package.filters.ResponseFilter
</filter-class>
</filter>

<filter>
<filter-name>anotherFilter</filter-name>
<filter-class>
com.package.filters.AnotherFilter
</filter-class>
</filter>
...

因此,此过滤器获取 Controller 响应,将其转换为字符串,将其作为 feild 添加到您的 RestResponse 类对象(带有状态和消息字段),将其序列化为 Json 对象并将完整的响应发送到客户端。

ResponseFilter 类:

public final class ResponseFilter implements Filter {

@Override
public void init(FilterConfig filterConfig) {
}

@Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {

ResponseWrapper responseWrapper = new ResponseWrapper((HttpServletResponse) response);

chain.doFilter(request, responseWrapper);

String responseContent = new String(responseWrapper.getDataStream());

RestResponse fullResponse = new RestResponse(/*status*/, /*message*/,responseContent);

byte[] responseToSend = restResponseBytes(fullResponse);

response.getOutputStream().write(responseToSend);

}

@Override
public void destroy() {
}

private byte[] restResponseBytes(RestResponse response) throws IOException {
String serialized = new ObjectMapper().writeValueAsString(response);
return serialized.getBytes();
}
}

chain.doFilter(request, responseWrapper) 方法调用链中的下一个过滤器,或者如果调用过滤器是链中的最后一个过滤器,则调用 servlet 逻辑。

HTTP servlet 响应包装器使用自定义 servlet 输出流,让包装器在 servlet 完成写出响应数据后对其进行操作。通常,在 servlet 输出流关闭后(基本上是在 servlet 提交它之后),这不能完成。这就是为 ServletOutputStream 类实现特定于过滤器的扩展的原因。

FilterServletOutputStream 类:

public class FilterServletOutputStream extends ServletOutputStream {

DataOutputStream output;
public FilterServletOutputStream(OutputStream output) {
this.output = new DataOutputStream(output);
}

@Override
public void write(int arg0) throws IOException {
output.write(arg0);
}

@Override
public void write(byte[] arg0, int arg1, int arg2) throws IOException {
output.write(arg0, arg1, arg2);
}

@Override
public void write(byte[] arg0) throws IOException {
output.write(arg0);
}
}

要使用 FilterServletOutputStream 类,应该实现一个可以充当响应对象的类。这个包装对象被发送回客户端,代替 servlet 生成的原始响应。

ResponseWrapper 类:

public class ResponseWrapper extends HttpServletResponseWrapper {

ByteArrayOutputStream output;
FilterServletOutputStream filterOutput;
HttpResponseStatus status = HttpResponseStatus.OK;

public ResponseWrapper(HttpServletResponse response) {
super(response);
output = new ByteArrayOutputStream();
}

@Override
public ServletOutputStream getOutputStream() throws IOException {
if (filterOutput == null) {
filterOutput = new FilterServletOutputStream(output);
}
return filterOutput;
}

public byte[] getDataStream() {
return output.toByteArray();
}
}

我认为这种方法可以很好地解决您的问题。

如果有不清楚的地方,请提出问题,如果我错了,请纠正我。

关于java - Spring MVC : How to modify json response sent from controller,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25020331/

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