Spring MVC with AspectJ

2019-05-30 18:02发布

问题:

I have a working spring mvc project. I want to log each request through my controllers with using AspectJ. The relevant code:

The Controller: (in package hu.freetime.controller)

@Controller
@RequestMapping("/")
public class BaseControllerImpl {
    @RequestMapping(method = RequestMethod.GET)
    public String index(Model model) {
        return "index";
    }
}

The Aspect:

@Aspect
public class ControllerAspectImpl {
    Logger logger = LoggerFactory.getLogger(ControllerAspectImpl.class);

    @Pointcut("execution(public * hu.freetime.controller.BaseControllerImpl.*(..))")
    public void logController() {
    }


    @Around("logController()")
    public void log(final ProceedingJoinPoint pjp) {
        MethodSignature signature = (MethodSignature) pjp.getSignature();
        Method method = signature.getMethod();
        logger.info("Calling Controller method: " + method.getName() + "()");
        try {
            pjp.proceed();
        } catch (Throwable e) {
            e.printStackTrace();
        }
    }
}

The WebAppInitializer:

public class CashflowWebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {

    @Override
    protected Class<?>[] getRootConfigClasses() {
        return new Class<?>[] { RootConfig.class };
    }

    @Override
    protected Class<?>[] getServletConfigClasses() {
        return new Class<?>[] { WebConfig.class };
    }

    @Override
    protected String[] getServletMappings() {
        return new String[] { "/" };
    }
}

The WebConfig class:

@Configuration
@EnableWebMvc
@EnableAspectJAutoProxy
@ComponentScan(basePackages = { "hu.freetime.controller", "hu.freetime.aspect" })
public class WebConfig extends WebMvcConfigurerAdapter {

    @Bean
    public ViewResolver viewResolver() {
        InternalResourceViewResolver resolver = new InternalResourceViewResolver();
        resolver.setPrefix("/WEB-INF/views/");
        resolver.setSuffix(".jsp");
        resolver.setExposeContextBeansAsAttributes(true);
        return resolver;
    }

    @Bean
    public ControllerAspectImpl getControllerAspect() {
        return new ControllerAspectImpl();
    }

    @Override
    public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
        configurer.enable();
    }
}

The problem is, that only one of the two components is working. If I "turn off" the AOP, the MVC works perfect, but when i "turn on", and I want to go to the main page, I get this error:

HTTP Status 404 - .../WEB-INF/views/.jsp
The requested resource is not available.

The strange thing is that it wants to map the ".jsp" instead of "index.jsp", as I wrote in the Controller's index() method. I debugged at runtime, and it did stop at the controller method.

How can I make it work?

回答1:

Your around advice does not return the result of pjp.proceed(). That is the return value of the advised method and must be returned by the advice! Otherwise you are turning the advised method into a void as well.

public **Object** log(final ProceedingJoinPoint pjp) {
...
    try {
        **return** pjp.proceed(); <<< !
    } catch (Throwable e) {
        e.printStackTrace();
    }    
}


回答2:

Use below code it will work

@Pointcut("execution(public * hu.freetime.*(..))")