问题描述
我有一个@AroundInvoke REST Web服务拦截器,我想将其用于记录常见数据,例如类和方法,远程IP地址和响应时间.
I have an @AroundInvoke REST Web Service interceptor that I would like to use for logging common data such as the class and method, the remote IP address and the response time.
使用InvocationContext获取类和方法名称很简单,只要被拦截的Rest Service在其参数列表中包含@Context HttpServletRequest,就可以通过HttpServletRequest获得远程IP.
Getting the class and method name is simple using the InvocationContext, and the remote IP is available via the HttpServletRequest, as long as the Rest Service being intercepted includes a @Context HttpServletRequest in its parameter list.
但是,某些REST方法的参数中没有HttpServletRequest,在这种情况下,我无法弄清楚如何获取HttpServletRequest对象.
However some REST methods do not have a HttpServletRequest in their parameters, and I can not figure out how to get a HttpServletRequest object in these cases.
例如,以下REST Web服务没有@Context HttpServletRequest参数
For example, the following REST web service does not have the @Context HttpServletRequest parameter
@Inject
@Default
private MemberManager memberManager;
@POST
@Path("/add")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
public Member add(NewMember member) throws MemberInvalidException {
return memberManager.add(member);
}
我尝试将其直接注入到我的Interceptor中,但是(在JBoss 6.1上)它始终为null ...
I have tried injecting it directly into my Interceptor, but (on JBoss 6.1) it is always null...
public class RestLoggedInterceptorImpl implements Serializable {
@Context
HttpServletRequest req;
@AroundInvoke
public Object aroundInvoke(InvocationContext ic) throws Exception {
logger.info(req.getRemoteAddr()); // <- this throws NPE as req is always null
...
return ic.proceed();
我想提出一种可靠的方法来访问HttpServletRequest对象-甚至只是Http Headers ...的建议,无论REST服务是否包含该参数.
I would like advice of a reliable way to access the HttpServletRequest object - or even just the Http Headers ... regardless of whether a REST service includes the parameter.
推荐答案
在Javadoc中研究了拦截器生命周期之后 http://docs.oracle.com/javaee/6/api/javax/interceptor/package-summary.html 我认为无法访问除了InvocationContext(由基础REST定义中的参数定义)中的Servlet上下文信息以外的任何Servlet上下文信息.这是因为Interceptor实例的生命周期与基础Bean相同,并且Servlet Request @Context必须注入到方法中而不是实例.但是,如果方法签名中除了InvocationContext之外的任何内容,则不会部署包含@AroundInvoke的Interceptor;否则,将不会部署.它不接受其他@Context参数.
After researching the Interceptor Lifecycle in the Javadoc http://docs.oracle.com/javaee/6/api/javax/interceptor/package-summary.html I don't think its possible to access any servlet context information other than that in InvocationContext (which is defined by the parameters in the underlying REST definition.) This is because the Interceptor instance has the same lifecycle as the underlying bean, and the Servlet Request @Context must be injected into a method rather than the instance. However the Interceptor containing @AroundInvoke will not deploy if there is anything other than InvocationContext in the method signature; it does not accept additional @Context parameters.
因此,允许拦截器获取HttpServletRequest的唯一答案是修改基础的REST方法定义,以包含@Context HttpServletRequest参数(如果需要,还包括HttpServletResponse).
So the only answer I can come up with to allow an Interceptor to obtain the HttpServletRequest is to modify the underlying REST method definitons to include a @Context HttpServletRequest parameter (and HttpServletResponse if required).
@Inject
@Default
private MemberManager memberManager;
@POST
@Path("/add")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
public Member add(NewMember member, @Context HttpServletRequest request, @Context HttpServletResponse response) throws MemberInvalidException {
...
}
拦截器然后可以遍历InvocationContext中的参数以获得HttpServletRequest
The interceptor can then iterate through the parameters in the InvocationContext to obtain the HttpServletRequest
@AroundInvoke
public Object aroundInvoke(InvocationContext ic) throws Exception {
HttpServletRequest req = getHttpServletRequest(ic);
...
return ic.proceed();
}
private HttpServletRequest getHttpServletRequest(InvocationContext ic) {
for (Object parameter : ic.getParameters()) {
if (parameter instanceof HttpServletRequest) {
return (HttpServletRequest) parameter;
}
}
// ... handle no HttpRequest object.. e.g. log an error, throw an Exception or whatever
这篇关于JEE6 REST服务@AroundInvoke拦截器正在注入一个空HttpServletRequest对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!