Intercept JAX-RS web service request to add JSON field

耗尽温柔 提交于 2019-11-29 00:30:23

Interceptors

It could be achieved with an interceptor.

Interceptors are intended to manipulate entities, via manipulating entity input/output streams. There are two kinds of interceptors, ReaderInterceptor and WriterInterceptor.

Reader interceptors are used to manipulate inbound entity streams. These are the streams coming from the "wire". So, using a reader interceptor you can manipulate request entity stream on the server side. Writer interceptors are used for cases where entity is written to the "wire" which on the server means when writing out a response entity

The following interceptor, which implements the ReaderInterceptor interface, allows you to modify the requested entity on server side:

@Provider
public class CustomReaderInterceptor implements ReaderInterceptor {

    @Override
    public Object aroundReadFrom(ReaderInterceptorContext context) 
                      throws IOException, WebApplicationException {

        InputStream stream = context.getInputStream();

        // Manipulate the HTTP entity using the InputStream

        context.setInputStream(stream);
        return context.proceed();
    }
}

Please note the above interceptor is global, that is, it will be executed for all resource methods.

When using Jackson, your ReaderInterceptor#aroundReadFrom(ReaderInterceptorContext) method implementation could be like:

// Create a Jackson ObjectMapper instance (it can be injected instead)
ObjectMapper mapper = new ObjectMapper();

// Parse the requested entity into a JSON tree
JsonNode tree = mapper.readTree(context.getInputStream());

// Add a property to the JSON
((ObjectNode) tree).put("field", "value");

// Set the input stream containing the manipulated JSON
context.setInputStream(new ByteArrayInputStream(mapper.writeValueAsBytes(tree)));

// Proceed to the next interceptor in the chain
context.proceed();

Name binding

To execute the interceptor for only some hand-picked resources methods, you can used name binding.

Name binding is a concept that allows to say to a JAX-RS runtime that a specific filter or interceptor will be executed only for a specific resource method. When a filter or an interceptor is limited only to a specific resource method we say that it is name-bound.

Filters can be assigned to a resource method using the @NameBinding annotation. The annotation is used as meta annotation for other user implemented annotations that are applied to a providers and resource methods.

A name binding annotation can be defined as following (the name of the annotation is up to you):

@NameBinding
@Retention(RUNTIME)
@Target({TYPE, METHOD})
public @interface CustomizeResponse { }

Place the above defined annotation on your interceptor class:

@Provider
@CustomizeResponse
public class CustomReaderInterceptor implements ReaderInterceptor {
    ...
}

To assign the interceptor to a resource method, place the above defined annotation on the resource method:

@GET
@CustomizeResponse
@Produces(MediaType.APPLICATION_JSON)
public Response myMethod() {
    ...
}

Name binding can be applied on resource classes as well. It means the interceptor will be executed for all resource methods of that resource class:

@Path("/foo")
@CustomizeResponse
public class MyResource() {
    ...
}

Note that global filters and interceptor are always executed, so even for resource methods which have any name binding annotations.

Additional resources

For more details on interceptors, have a look at Jersey documentation.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!