Vit*_*nov 21 java spring json spring-mvc
我用这样的控制器构建了一个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();
}
}
Run Code Online (Sandbox Code Playgroud)
它工作正常,但现在我需要修改所有响应并向所有响应添加"status"和"message"字段.我读过一些解决方案:
如果我想将从控制器方法返回的值包装到类的对象中,您能否提出一些其他的,一般的和正确的解决方案:
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
}
Run Code Online (Sandbox Code Playgroud)
Ale*_*der 23
我遇到过类似的问题,建议您使用Servlet过滤器来解决它.
Servlet过滤器是Java类,可以在Servlet编程中用于在客户端访问后端资源之前拦截客户端的请求,或者在将服务器发送回客户端之前操纵服务器的响应.
您的过滤器必须实现javax.servlet.Filter接口并覆盖三个方法:
public void doFilter (ServletRequest, ServletResponse, FilterChain)
Run Code Online (Sandbox Code Playgroud)
每次请求/响应对通过链时都会调用此方法,因为客户端请求链末端的资源.
public void init(FilterConfig filterConfig)
Run Code Online (Sandbox Code Playgroud)
在过滤器投入使用之前调用,并设置过滤器的配置对象.
public void destroy()
Run Code Online (Sandbox Code Playgroud)
在过滤器停止服务后调用.
可以使用任意数量的过滤器,执行顺序与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>
...
Run Code Online (Sandbox Code Playgroud)
因此,此过滤器获取控制器响应,将其转换为String,作为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();
}
}
Run Code Online (Sandbox Code Playgroud)
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);
}
}
Run Code Online (Sandbox Code Playgroud)
要使用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();
}
}
Run Code Online (Sandbox Code Playgroud)
我认为这种方法对您的问题来说是一个很好的解决方案.
如果问题不明确,请提出问题,如果我错了,请纠正我.
sma*_*wjw 23
如果使用spring 4.1或更高版本,则可以在写入正文之前使用ResponseBodyAdvice来自定义响应.
| 归档时间: |
|
| 查看次数: |
34597 次 |
| 最近记录: |