我已经使用像这样的控制器构建了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();
}
}
它工作正常,但现在我需要修改所有响应,并向所有响应添加“状态”和“消息”字段。我已经阅读了一些解决方案:
如果我想将控制器方法返回的值包装到类的对象中,可以提出其他一些通用且正确的解决方案:
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过滤器来解决它。
Servlet过滤器是Java类,可以在Servlet编程中使用这些Java类在客户端访问后端资源之前拦截来自客户端的请求,或者在将服务器发送回客户端之前操纵来自服务器的响应。
您的过滤器必须实现javax.servlet.Filter接口并重写三个方法:
public void doFilter (ServletRequest, ServletResponse, FilterChain)
每当客户端对链末端的资源提出请求时,每次通过该链通过一个请求/响应对时都会调用此方法。
public void init(FilterConfig filterConfig)
在过滤器投入使用之前调用,并设置过滤器的配置对象。
public void destroy()
在过滤器停止使用后调用。
可以使用任意数量的过滤器,执行的顺序将与在web.xml中html" target="_blank">定义的顺序相同。
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>
...
因此,此过滤器获取控制器响应,将其转换为String,将其作为字段添加到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();
}
}
我认为这种方法将是解决您问题的好方法。
请问一个问题,如果不清楚,请纠正我,如果我错了。
我用这样的控制器构建了一个json REST服务: 它工作得很好,但是现在我需要修改所有的响应,并为它们添加“状态”和“消息”字段。我读过一些解决方案: 从所有控制器方法返回某个特定类的对象,例如RestResponse,它将包含“状态”和“消息”字段(但这不是通用解决方案,因为我必须修改所有控制器并以新样式编写新控制器) 拦截所有带有方面的控制器方法(但在这种情况下,我无法更改返回类型) 如果我
我有一个使用Spring MVC 3.1.3的应用程序和使用Dojo1.4开发的UI。应用程序只有很少的控制器处理通过上传的二进制文件。控制器发送一个json响应,该响应必须用 我实现了web.xml中定义的自定义筛选器: 提前道谢。 更新:我禁用了Spring Security性,并用普通spring mvc进行了测试,但问题仍然存在。我修改了标题和问题描述。
问题内容: 我正在编辑内置的表单。 我在对话框中显示该表单,然后提交。 数据已正确输入数据库。 但是我不知道是否需要将一些寄回。其实我对事情有点困惑。 假设我在表中使用``jQuery添加了一行,当我提交表单时,然后在提交数据之后,我想发回那些行数据,以便我可以动态添加表行以显示添加的数据。 我很困惑如何获取这些数据。 这是我当前的代码: 这只是带有成功消息的模板。 问题答案: Symfony 2
我想从spring控制器返回一个字符串(json字符串)作为它接收到的AJAX调用的响应,响应可能会根据我是否提交了@Valid表单而有所不同。这就是我处理它的方式,我想知道这是否被认为是最佳实践?请注意,我使用的是@RestController,所以@ResonseBody应用所有方法。
在到达spring控制器之前,如何从UI端修改请求体中发送的JSON对象? 我尝试添加过滤器,但是一旦我从请求(servletrequest.getReader())读取,然后将请求转发到过滤器链中的下一个过滤器,它就会失败(请求无法到达控制器)。 使用这个,我得到了字符串中的JSON,但我无法弄清楚如何将其放回请求中。
我有过 我通过这种方式传递profileJson: 但是我的配置文件Json对象具有所有空字段。我应该怎么做才能让Spring解析我的json?