项目中AOP的实例应用

Posted 断剑重铸之时

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了项目中AOP的实例应用相关的知识,希望对你有一定的参考价值。

其中包括了权限管理、表单验证、事务管理、信息过滤、拦截器、过滤器、页面转发等等。

公司项目的应用:(涉及用户验证登录以及用户是否有管理员权限、心理用户权限等),还有涉及的其他日志管理代码就不一一举例了;

/**
 * 登录拦截器(登录判断)
 * @author alex
 *
 */
public class LoginInterceptor extends HandlerInterceptorAdapter {

    @Autowired
    private UserService userService;
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        if (handler instanceof HandlerMethod) {
            HandlerMethod handlerMethod = (HandlerMethod) handler;
            //check login
            Login login = handlerMethod.getMethodAnnotation(Login.class);
            if (null == login) {
                return true;
            }
            int userId = 0;
            String uid = CookieUtil.getValueByName(request, CookieUtil.SESSION_USER);
            if(NumberUtils.isNumber(uid)){
                userId = Integer.valueOf(uid);
            }
            if(userId==0 || !userService.isLogined(userId, CookieUtil.getValueByName(request, CookieUtil.SESSION_ID))){
                response.sendRedirect("/login");
                return false;
            }
            //set user info
            User user = userService.getUserById(userId);
            request.setAttribute("userSession", user);
            request.setAttribute("loginUsername",user.getUsername());
            request.setAttribute("loginUserId",user.getId());
            //******* 是内部测试的心理账户
            request.setAttribute("psychologyUser", user.getType == *** || "*******".equals(user.getCellphone()));
            //check admin permission
            Admin admin = handlerMethod.getMethodAnnotation(Admin.class);
            if (admin!=null && !user.isAdmin()) {
                response.sendRedirect("/error/no_permission");
                return false;
            }
            return true;
        }
        return true;
    }
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
            throws Exception {
    }
}
/**
 * 登录注解
 * @author Alex
 *
 */
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Login {
    int value() default 0;
}


/**
 * 管理员注解
 * @author Alex
 *
 */
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Admin {
    int value() default 0;
}

 

一般情况下,对来自浏览器的请求的拦截,是利用Filter实现的,这种方式可以实现Bean预处理、后处理。 
Spring MVC的拦截器不仅可实现Filter的所有功能,还可以更精确的控制拦截精度。 

Spring为我们提供了org.springframework.web.servlet.handler.HandlerInterceptorAdapter这个适配器,继承此类,可以非常方便的实现自己的拦截器。他有三个方法:

  1. public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)    
  2.         throws Exception {    
  3.         return true;    
  4.     }    
  5.     public void postHandle(    
  6.             HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView)    
  7.             throws Exception {    
  8.     }    
  9.     public void afterCompletion(    
  10.             HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)    
  11.             throws Exception {    
  12.     }    


分别实现预处理、后处理(调用了Service并返回ModelAndView,但未进行页面渲染)、返回处理(已经渲染了页面) 

preHandle预处理回调方法,实现处理器的预处理(如登录检查),第三个参数为响应的处理器;

     返回值:true表示继续流程(如调用下一个拦截器或处理器);

             false表示流程中断(如登录检查失败),不会继续调用其他的拦截器或处理器,此时我们需要通过response来产生响应;

postHandle后处理回调方法,实现处理器的后处理(但在渲染视图之前),此时我们可以通过modelAndView(模型和视图对象)对模型数据进行处理或对视图进行处理,modelAndView也可能为null。

afterCompletion整个请求处理完毕回调方法,即在视图渲染完毕时回调,如性能监控中我们可以在此记录结束时间并输出消耗时间,还可以进行一些资源清理,类似于try-catch-finally中的finally,但仅调用处理器执行链中preHandle返回true的拦截器的afterCompletion

AOP相关配置:<tx:advice id="txAdvice" transaction-manager="transactionManager">  

        <tx:attributes>  
            <tx:method name="save*" propagation="REQUIRED" rollback-for="Exception"/>  
            <tx:method name="insert*" propagation="REQUIRED"  rollback-for="Exception"/>  
            <tx:method name="del*" propagation="REQUIRED" rollback-for="Exception"/>  
            <tx:method name="update*" propagation="REQUIRED" rollback-for="Exception"/>  
            <tx:method name="find*" read-only="true" />  
            <tx:method name="get*" read-only="true" />  
            <tx:method name="select*" read-only="true" />  
        </tx:attributes>  
</tx:advice>  
   
<aop:config proxy-target-class="true">  
       <aop:advisor pointcut="execution( * com.zhaozhi.spider.service.service.*.*(..))" advice-ref="txAdvice" />  
</aop:config>
//....

 

以上是关于项目中AOP的实例应用的主要内容,如果未能解决你的问题,请参考以下文章

Dora.Interception, 为.NET Core度身打造的AOP框架[4]:演示几个典型应用

创建片段而不从 java 代码实例化它

spring mvc的项目中实现aop日志记录

spring aop 问题,不能进入切点

片段事务中的实例化错误

Spring AOP之 动态代理实例