由于AOP配置,Spring3 MVC DispatcherServlet没有JSON结果

时间:2012-08-29 15:34:39

标签: json rest spring-mvc spring-aop

当我们配置Spring AOP时,JSON结果将消失:AOPExression1

<aop:pointcut id="dmhMethodExecution"
            expression="within(com.aditya.dmh..*)" />

所以我添加了一个排除:AOPExpression1为AOpExpression2

<aop:pointcut id="dmhMethodExecution"
   expression="within(com.aditya.dmh..*) 
        and !within(com.aditya.dmh.controller..*)" />

在ASPECTJ表达式中 我仍然没有从控制器中看到我的JSON结果,这是一个宁静的实现。

package com.aditya.dmh.controller;

@Controller
public class EmployeeController {

private EmployeeServiceInterface employeeService;

@Autowired
public void setEmployeeService(EmployeeServiceInterface employeeService) {
    this.employeeService = employeeService;
}

@RequestMapping("/employeeservices/1/allemployees.view")
public @ResponseBody Result<EmployeeModel> getEmployees(){
    return employeeService.getEmployees(0, 10);

}
}

当我使用log4j作为DEBUG消息时,我看到以下内容:

15:37:04.214 [http-8090-1] DEBUG o.s.web.servlet.DispatcherServlet - Null ModelAndView  returned to DispatcherServlet with name 'dmhServiceDispatcher': assuming HandlerAdapter completed request handling

15:37:04.214 [http-8090-1] DEBUG o.s.web.servlet.DispatcherServlet - Successfully completed request

当我删除AOP时,JSON结果开始出现,我看到了额外的调试消息。

17:11:36.270 [http-8090-2] DEBUG o.s.w.s.m.m.a.RequestResponseBodyMethodProcessor - Written [com.aditya.Result@8a85268] as "application/json;charset=UTF-8" using [org.springframework.http.converter.json.MappingJackson2HttpMessageConverter@62ba2e48]

查看Spring论坛,我了解转换器是在

时自动配置的
<mvc:annotation-driven/>

被使用。

我配置AOP的问题是否与RequestResponseBodymethodProcessor没有被调用有关。

当我使用AOPExpression1时,这是否与我的控制器周围创建的代理有关。为什么AOPExpression2中的排除仍然存在问题。

Anyhelp将不胜感激

3 个答案:

答案 0 :(得分:0)

我相信拦截对控制器的请求你应该使用MVC拦截器而不是方面。我所做的是将这个文件放入applicationContext.xml:

<mvc:interceptors>
    <mvc:interceptor>
        <mvc:mapping path="/employeeservices/1/allemployees.view"/>
        <bean class="com.aditya.dmh.interceptor.ResultInterceptor" />
    </mvc:interceptor>
</mvc:interceptors>

现在,类ResultInterceptor是您放置要完成的代码的位置,例如:

@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {

    log.info("--- preHandle --- ");

    return true;
}

至少这是我做的方式。

希望它有所帮助。

答案 1 :(得分:0)

这是一个猜测:

我认为正在发生的是基于CGLIB的动态代理正在为您的控制器创建(尽管您已在新的切入点表达式中明确地将其排除),如果发生这种情况,则@RequestMapping注释未被正确检测到(通过`)所以控制器不在那里处理你的REST请求。

你可以尝试一些事情:

  1. 使用与控制器处理的方法完全相同的方法为控制器设置接口,并在其中放置@RequestMapping注释,这将处理创建动态代理的情况,并且应该按预期工作,即使动态代理被创建..

  2. 使用您的切入点表达式稍微玩一下,看看为什么可能会创建控制器的代理。

答案 2 :(得分:0)

在这个背景下解决我们的问题

我们发现整个事情都与AOP配置中的环境建议有关。

修复前

public void logAround(ProceedingJoinPoint joinPoint) throws Throwable {
    long startTime = System.currentTimeMillis();
    joinPoint.proceed();
    long totalTime = System.currentTimeMillis() - startTime;

    log.debug(buildLogMessage(new StringBuilder().append(METHOD_AROUND_ID)
            .append("[").append(totalTime).append("] ").toString(),
            joinPoint));
    return returnValue;
}

修复后

public Object logAround(ProceedingJoinPoint joinPoint) throws Throwable {
    long startTime = System.currentTimeMillis();
    Object returnValue = joinPoint.proceed();
    long totalTime = System.currentTimeMillis() - startTime;

    log.debug(buildLogMessage(new StringBuilder().append(METHOD_AROUND_ID)
            .append("[").append(totalTime).append("] ").toString(),
            joinPoint));
    return returnValue;
}

void有效地确保logAround发送的响应对象没有传递回RequestResponseBodyMethodProcessor

一旦我们抓住它并且返回cglib代理将响应发送回处理器&amp;将响应发回客户端。