手机站 广告联系

淮安新闻网——淮安门户网淮安人才网-淮安求职找工作门户www.hallimvalve.cn

springmvc中aop对controller的切面编程

来源:淮安新闻网 作者:淮安新闻网 人气: 发布时间:2019-09-15
摘要:概述:最近在开发一个基础应用服务系统,利用加密的token标识来校验访问者的身份。几乎每一个接口都需要校验token。故打算采用aop面向切面编程,一次性对所有接口进行身份认证;遇

springmvc中aop对controller的切面编程

概述:

最近在开发一个基础应用服务系统,利用加密的token标识来校验访问者的身份。几乎每一个接口都需要校验token。故打算采用aop面向切面编程,一次性对所有接口进行身份认证;

遇见的问题:

切面配置没有问题的情况下,junit单元测试调用controller里面的方法,可以触发切点,实现切面编程。但是web部署到tomcat后,直接url访问触发切点失败!

详情描述:

切面类:

import org.aspectj.lang.annotation.AfterReturning;

import org.aspectj.lang.annotation.AfterThrowing;

import org.aspectj.lang.annotation.Aspect;

import org.aspectj.lang.annotation.Before;

import org.aspectj.lang.annotation.Pointcut;

import org.springframework.stereotype.Component;

/**

*

* @Description: TODO( token的校验 )

* @author: mayao

* @date 2016年10月20日 下午5:47:37

*/

@Aspect

@Component

public class UserTokenInterceptor {

http://controller包的子包里面任何方法

@Pointcut("execution(public * com.test.controller.*.*(..))")

public void checkToken(){

}

@Before("checkToken()")

public void beforeCheckToken(){

System.out.println("调用方法之前。。。。");

}

@AfterReturning("checkToken()")

public void afterCheckToken(){

System.out.println("调用方法结束之后。。。。");

}

http://抛出异常时才调用

@AfterThrowing("checkToken()")

public void afterThrowing()

{

System.out.println("校验token出现异常了......");

}

}

控制器:

/**

*

* @Description: TODO( 请求token )

* @author: mayao

* @date 2016年10月19日 下午5:11:25

*/

@Controller

@RequestMapping("/mayao")

public class TokenController {

@RequestMapping(value="/test",method=RequestMethod.GET)

public void test(){

System.out.println("调用controller里面的方法!!!");

}

}

配置文件:

applicationContext.xml 部分代码片段

spring-mvc.xml 部分代码片段

junit测试代码

@Test

public void controllerAOPTest(){

ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("classpath*:applicationContext.xml");

ctx.start();

TokenController token = (TokenController)ctx.getBean(TokenController.class);

token.test();

}

测试结果:

调用方法之前。。。。

调用controller里面的方法!!!

调用方法结束之后。。。。

测试时成功的!!

然后启动tomcat,访问链接 http:http://localhost/项目名/mayao/test,结果是:调用controller里面的方法!!!

切点没有触发!!

原因:

经过查找资料及自己验证得出:

1.是父子容器的问题

2.我的切面代码和连接点,通知都没有问题,问题出在了配置信息上面。

(部分借鉴)CGLIB代理配置在了applicationContext.xml 核心配置文件中,该配置文件会被ContextLoaderListenerclass加载,Spring会创建一个WebApplicationContext上下文,称为父上下文(父容器) ,保存在ServletContext中,key为WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE的值。

而spring-mvc.xml是DispatcherServlet,可以同时配置多个,每个 DispatcherServlet有一个自己的上下文对象(WebApplicationContext),称为子上下文(子容器),子上下文可以访问父上下文中的内容,但父上下文不能访问子上下文中的内容。 它也保存在 ServletContext中,key是”org.springframework.web.servlet.FrameworkServlet.CONTEXT”+Servlet名称

当spring加在父容器的时候就会去找切入点,但是这个时候切入的controller是在子容器中的,父容器是无法访问子容器,所以就拦截不到。如果将上述的配置文件放到spring-mvc.xml中,那么问题就解决了。我已经测试可以通过URL访问触发切点了。

解决方法:

将配置信息:

从applicationContext.xml移到spring-mvc.xml中就可以了

总结:

归根结底来说,其实是bean的代理问题,涉及普通的bean,service,controller。下面的要注意。

Spring MVC 和 Spring 整合的时候,SpringMVC的spring-mvc.xml文件中配置扫描包,不要包含 service的注解,Spring的applicationContext.xml文件中配置扫描包时,不要包含controller的注解。

错误如下:

Spring MVC启动时的配置文件,包含组件扫描、url映射以及设置freemarker参数,让spring不扫描带有@Service注解的类。为什么要这样设置?

因为spring-mvc.xml与applicationContext.xml不是同时加载,如果不进行这样的设置,那么,spring就会将所有带@Service注解的类都扫描到容器中,等到加载applicationContext.xml的时候,会因为容器已经存在Service类,使得cglib将不对Service进行代理,直接导致的结果就是在applicationContext 中的事务配置不起作用,发生异常时,无法对数据进行回滚。以上就是原因所在。

不过不必太当心这个,实际应用中这样的配置(指定service,controller扫描的)也很少。

责任编辑:淮安新闻网
这里设置第三方评论代码

最火资讯

百度新闻独家出品

新闻由机器选取每5分钟自动更新

手机:18800000000 邮箱:180000@qq.com
地址:北京市河南岸国商大厦B-6-B