Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/373.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java SpringMVC:如何修改控制器发送的json响应_Java_Json_Spring_Spring Mvc - Fatal编程技术网

Java SpringMVC:如何修改控制器发送的json响应

Java SpringMVC:如何修改控制器发送的json响应,java,json,spring,spring-mvc,Java,Json,Spring,Spring Mvc,我构建了一个json REST服务,其中包含如下控制器: @Controller @RequestMapping(value = "/scripts") public class ScriptController { @Autowired private ScriptService scriptService; @RequestMapping(method = RequestMethod.GET) @ResponseBody public List&l

我构建了一个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();
    }
}

我遇到过类似的问题,建议您使用Servlet过滤器来解决它

Servlet过滤器是Java类,可以在Servlet编程中使用它来拦截来自客户端的请求,然后再访问后端的资源,或者在将请求发送回客户端之前处理来自服务器的响应

过滤器必须实现javax.servlet.filter接口并覆盖三种方法:

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>
...
doFilter(request,responseWrapper)方法调用链中的下一个过滤器,或者如果调用过滤器是链中的最后一个过滤器,则调用servlet逻辑

HTTPServlet响应包装器使用一个定制的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();
}
}
我认为这种方法会很好地解决你的问题


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

如果您使用spring 4.1或更高版本,您可以使用自定义
在写正文之前的响应

我不知道类的确切名称,但在SpringRESTful中应该存在响应处理程序类,就像restful的Wink实现中的ResponseHandler类一样。修改响应后,可以在此处明确设置响应实体。希望它至少能告诉你该去哪里看,尽管这不是正确的答案。在MVC中,类似这样的东西可能最好重写处理程序。这是解决你问题的最干净、最不神奇的方法。不幸的是,懒惰并不总是值得的。您还需要重写客户端,因为它们将以新格式接收数据。在我看来,选项1是证明您的服务未来的更好方法。可能重复@SergeBallesta您认为重复的问题与此问题无关。@Jimmy谢谢,现在我正在研究使用spring拦截器和servlet筛选器的解决方案。这可能不是正确的答案。通知仅在呼叫到达控制器时执行。首先执行过滤链,如果出现类似AuthException的异常,则不会应用通知。
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);
}
}
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();
}
}