Dans notre application, nous utilisons JSON pour la demande et la réponse. Les méthodes de contrôleur sont annotées avec @requestbody (). L'objet étant retourné par ex. Transfère. Je voudrais obtenir la maintien de cet objet former le @Responsebody. J'ai configuré une méthode d'intercepteur posthandle: Alors, comment puis-je obtenir le JSON dans cette méthode posthandle? P> Merci d'avance
GM P> P>
4 Réponses :
Comme Pavel dit, vous ne pouvez probablement pas arriver à la réponse JSON de cette façon. Je pense que le meilleur pari est de mettre en œuvre un filtre que Regarde la réponse avant de l'écrire au client. Jetez un coup d'œil à autre expérience pour un point de départ. P>
Merci tout ce que je vais essayer cela.
comme Pavel Horal déjà mentionné, lorsque posthandle () code> est appelé, L'objet corporel de réponse est déjà converti en JSON et écrit en réponse. Vous pouvez essayer d'écrire votre propre annotation personnalisée et votre propre aspect afin d'intercepter les objets du corps de réponse du contrôleur. // custom annotation
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyCustomAnnotation {
}
// aspect
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;
@Aspect
@Component
public class MyCustomAnnotationAspect {
@Around(value = "@annotation(org.package.MyCustomAnnotation)", argNames = "pjp")
public Object aroundAdvice(final ProceedingJoinPoint pjp) {
// this is your response body
Object responseBody = pjp.proceed();
return responseBody;
}
}
Merci tout ce que je vais essayer cela.
J'ai enfin une solution de travail (mais pas élégante) pour ce cas. Je pense que cela peut avoir une meilleure solution, mais je ne trouve pas que.
Au début, j'ai été créé une enveloppe de demande et de réponse qui encapsule la charge utile, faisant ma demande de flux de saisie et de réponse de réponse réutilisable et répréhensible. Je dois l'utiliser dans mon filtre pour manipuler à la fois la demande et la charge de réponse des charges utiles. P>
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletInputStream;
import javax.servlet.ServletOutputStream;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpServletResponseWrapper;
import org.springframework.context.ApplicationContext;
import br.com.vivo.core.controller.impl.utils.ApplicationContextUtils;
import com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
@WebFilter(urlPatterns = { "/*" })
public class HeadBodyFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
ApplicationContext applicationContext = ApplicationContextUtils.getApplicationContext();
ObjectMapper objectMapper = (ObjectMapper) applicationContext.getBean("jacksonObjectMapper");
JsonFactory jsonFactory = objectMapper.getFactory();
ByteResponseWrapper byteResponseWrapper = new ByteResponseWrapper((HttpServletResponse) response);
ByteRequestWrapper byteRequestWrapper = new ByteRequestWrapper((HttpServletRequest) request);
String jsonRequestString = new String(byteRequestWrapper.getBytes());
JsonParser requestParser = jsonFactory.createParser(jsonRequestString);
JsonNode rootRequestNode = objectMapper.readTree(requestParser);
if(rootRequestNode != null && rootRequestNode.has("body")) {
JsonNode requestBody = rootRequestNode.get("body");
writeJsonIntoRequest(byteRequestWrapper, requestBody, objectMapper);
}
chain.doFilter(byteRequestWrapper, byteResponseWrapper);
String jsonResponseString = new String(byteResponseWrapper.getBytes(), response.getCharacterEncoding());
JsonParser responseParser = jsonFactory.createParser(jsonResponseString);
JsonNode rootResponseNode = objectMapper.readTree(responseParser);
Object head = "Whoo hoo!";
ObjectNode responseObjectWrapper = objectMapper.createObjectNode();
responseObjectWrapper.put("head", objectMapper.valueToTree(head));
responseObjectWrapper.put("body", rootResponseNode);
writeJsonIntoResponse(response, responseObjectWrapper, objectMapper);
}
private void writeJsonIntoRequest(ByteRequestWrapper request,
JsonNode requestBody, ObjectMapper objectMapper) throws IOException {
String json = objectMapper.writeValueAsString(requestBody);
request.replaceRequestPayload(json.getBytes());
}
@Override
public void destroy() {
}
/**
* Escreve o json no response
*
* @param response
* @param rootNode
* @throws IOException
*/
private void writeJsonIntoResponse(final ServletResponse response, final JsonNode responseBody, final ObjectMapper objectMapper) throws IOException {
String json = objectMapper.writeValueAsString(responseBody);
// escreve o json
response.getOutputStream().write((json + "\r\n").getBytes(response.getCharacterEncoding()));
}
static class ByteResponseWrapper extends HttpServletResponseWrapper {
private PrintWriter writer;
private ByteOutputStream output;
public byte[] getBytes() {
writer.flush();
return output.getBytes();
}
public ByteResponseWrapper(HttpServletResponse response) {
super(response);
output = new ByteOutputStream();
writer = new PrintWriter(output);
}
@Override
public PrintWriter getWriter() {
return writer;
}
@Override
public ServletOutputStream getOutputStream() throws IOException {
return output;
}
}
static class ByteRequestWrapper extends HttpServletRequestWrapper {
byte[] requestBytes = null;
private ByteInputStream byteInputStream;
public ByteRequestWrapper(HttpServletRequest request) throws IOException {
super(request);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
InputStream inputStream = request.getInputStream();
byte[] buffer = new byte[4096];
int read = 0;
while ( (read = inputStream.read(buffer)) != -1 ) {
baos.write(buffer, 0, read);
}
replaceRequestPayload(baos.toByteArray());
}
public byte[] getBytes() {
return requestBytes;
}
@Override
public BufferedReader getReader() throws IOException {
return new BufferedReader(new InputStreamReader(getInputStream()));
}
@Override
public ServletInputStream getInputStream() throws IOException {
return byteInputStream;
}
public void replaceRequestPayload(byte[] newPayload) {
requestBytes = newPayload;
byteInputStream = new ByteInputStream(new ByteArrayInputStream(requestBytes));
}
}
static class ByteOutputStream extends ServletOutputStream {
private ByteArrayOutputStream bos = new ByteArrayOutputStream();
@Override
public void write(int b) throws IOException {
bos.write(b);
}
public byte[] getBytes() {
return bos.toByteArray();
}
}
static class ByteInputStream extends ServletInputStream {
private InputStream inputStream;
public ByteInputStream(final InputStream inputStream) {
this.inputStream = inputStream;
}
@Override
public int read() throws IOException {
return inputStream.read();
}
}
}
Étant donné que la question a été postée, ResponseBodyAdvice a été ajouté au printemps MVC 4.1. Cette interface permet aux applications de modifier ou de modifier complètement le corps avant l'application du convertisseur. Documentation pour intercepter Les demandes ont également été mises à jour spécifiquement pour ce problème: P>
Notez que la méthode posthandle de handlerinterint n'est pas toujours parfaitement adaptée à une utilisation avec @ReSponsebody et méthodes de réponse. Dans de tels cas, un site httpmessageconverter écrit et commet la réponse avant que POSTHANDLE n'est appelé, ce qui rend impossible la modification de la réponse, par exemple pour ajouter un en-tête. Au lieu de cela, une application peut implémenter la réponse de réponse et la déclarer comme un haricot @ControllerAdvice ou la configurer directement sur DemandeMappingHandlerDapter. P> blockQuote>
C'est une bonne. Je ne pense pas que vous puissiez accéder à l'objet code> @Responsebody code> tel qu'il est manipulé (marshaled dans le flux de sortie de réponse de servlet) bien avant que la commande ne revienne sur
Disternersservlet CODE> (qui est responsable pour appeler des intercepteurs de gestionnaire). Selon votre cas d'utilisation, vous devrez trouver une manière différente.