zoukankan      html  css  js  c++  java
  • spring:注解配置AOP

    注解配置AOP(使用 AspectJ 类库实现的),大致分为三步: 
    1. 使用注解@Aspect来定义一个切面,在切面中定义切入点(@Pointcut),通知类型(@Before, @AfterReturning,@After,@AfterThrowing,@Around). 
    2. 开发需要被拦截的类。 
    3. 将切面配置到xml中,当然,我们也可以使用自动扫描Bean的方式。这样的话,那就交由Spring AoP容器管理。 

    另外需要引用 aspectJ 的 jar 包: aspectjweaver.jar aspectjrt.jar 

    ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

    pom中的jar包支持

    <!--spring-aop依赖 -->
    <dependency>
    <groupId>org.aspectj</groupId>
    <artifactId>aspectjweaver</artifactId>
    <version>1.7.4</version>
    </dependency>
    <dependency>
    <groupId>org.aspectj</groupId>
    <artifactId>aspectjrt</artifactId>
    <version>1.7.4</version>
    </dependency>
    <dependency>
    <groupId>org.aspectj</groupId>
    <artifactId>aspectjtools</artifactId>
    <version>1.7.4</version>
    </dependency>
    <dependency>
    <groupId>cglib</groupId>
    <artifactId>cglib</artifactId>
    <version>2.2</version>
    </dependency>
    -----------------------------------------------------------------------------------------------------------------
    自定义注解Controller部分
    package cn.cjq.util.aop;

    import java.lang.annotation.*;

    /**
    *自定义注解 拦截Controller
    */

    @Target({ElementType.PARAMETER, ElementType.METHOD})
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    public @interface SystemControllerLog {
    String description() default "";
    }
    ---------------------------------------------------------------------------------------------------------------
    自定义注解Service业务部分
    package cn.cjq.util.aop;
    import java.lang.annotation.*;
    /**
    *自定义注解 拦截service
    */
    @Target({ElementType.PARAMETER, ElementType.METHOD})
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    public @interface SystemServiceLog {
    String description() default "";
    }
    --------------------------------------------------------------------------------------------------------------------------------
    切面类
    package cn.cjq.util.aop;

    import cn.cjq.entity.User;
    import org.aspectj.lang.JoinPoint;
    import org.aspectj.lang.annotation.*;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.stereotype.Component;
    import org.springframework.web.context.request.RequestContextHolder;
    import org.springframework.web.context.request.ServletRequestAttributes;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpSession;
    import java.lang.reflect.Method;

    /**
    * 切点类
    * @author cjq
    * @since 2017-11-28
    * @version 1.0
    */
    @Aspect
    @Component
    public class SystemLogAspect {

    //本地异常日志记录对象
    private static final Logger logger = LoggerFactory.getLogger(SystemLogAspect. class);

    //Service层切点
    @Pointcut("@annotation(cn.cjq.util.aop.SystemServiceLog)")
    public void serviceAspect() {
    }

    //Controller层切点
    @Pointcut("@annotation(cn.cjq.util.aop.SystemControllerLog)")
    public void controllerAspect() {
    }

    /**
    * 前置通知 用于拦截Controller层记录用户的操作
    *
    * @param joinPoint 切点
    */
    @Before("controllerAspect()")
    public void doBefore(JoinPoint joinPoint) {

    HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
    HttpSession session = request.getSession();
    //读取session中的用户
    User user = (User) session.getAttribute("user");
    //请求的IP
    String ip = request.getRemoteAddr();
    try {
    //*========控制台输出=========*//
    System.out.println("=====前置通知开始=====");
    System.out.println("请求方法:" + (joinPoint.getTarget().getClass().getName() + "." + joinPoint.getSignature().getName() + "()"));
    System.out.println("方法描述:" + getControllerMethodDescription(joinPoint));
    //System.out.println("请求人:" + user.getUsername());
    System.out.println("请求IP:" + ip);
    //*========数据库日志=========*//
    /*Log log = SpringContextHolder.getBean("logxx");
    log.setDescription(getControllerMethodDescription(joinPoint));
    log.setMethod((joinPoint.getTarget().getClass().getName() + "." + joinPoint.getSignature().getName() + "()"));
    log.setType("0");
    log.setRequestIp(ip);
    log.setExceptionCode( null);
    log.setExceptionDetail( null);
    log.setParams( null);
    log.setCreateBy(user);
    log.setCreateDate(DateUtil.getCurrentDate());
    //保存数据库
    logService.add(log);*/
    System.out.println("=====前置通知结束=====");
    } catch (Exception e) {
    System.out.println("=====Controller通知结束=====");
    //记录本地异常日志
    logger.error("==前置通知异常==");
    logger.error("异常信息:{}", e.getMessage());
    }
    }

    /**
    * 异常通知 用于拦截service层记录异常日志
    *
    * @param joinPoint
    * @param e
    */
    @AfterThrowing(pointcut = "serviceAspect()", throwing = "e")
    public void doAfterThrowing(JoinPoint joinPoint, Throwable e) {
    HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
    HttpSession session = request.getSession();
    //读取session中的用户
    User user = (User) session.getAttribute("user");
    //获取请求ip
    String ip = request.getRemoteAddr();
    //获取用户请求方法的参数并序列化为JSON格式字符串
    String params = "";
    if (joinPoint.getArgs() != null && joinPoint.getArgs().length > 0) {
    for ( int i = 0; i < joinPoint.getArgs().length; i++) {
    params += joinPoint.getArgs()[i] + ";";
    }
    }
    try {
    /*========控制台输出=========*/
    System.out.println("=====异常通知开始=====");
    System.out.println("异常代码:" + e.getClass().getName());
    System.out.println("异常信息:" + e.getMessage());
    System.out.println("异常方法:" + (joinPoint.getTarget().getClass().getName() + "." + joinPoint.getSignature().getName() + "()"));
    System.out.println("方法描述:" + getServiceMthodDescription(joinPoint));
    //System.out.println("请求人:" + user.getUsername());
    System.out.println("请求IP:" + ip);
    System.out.println("请求参数:" + params);
    /*==========数据库日志=========*/
    /*Log log = SpringContextHolder.getBean("logxx");
    log.setDescription(getServiceMthodDescription(joinPoint));
    log.setExceptionCode(e.getClass().getName());
    log.setType("1");
    log.setExceptionDetail(e.getMessage());
    log.setMethod((joinPoint.getTarget().getClass().getName() + "." + joinPoint.getSignature().getName() + "()"));
    log.setParams(params);
    log.setCreateBy(user);
    log.setCreateDate(DateUtil.getCurrentDate());
    log.setRequestIp(ip);
    //保存数据库
    logService.add(log);*/
    System.out.println("=====异常通知结束=====");
    } catch (Exception ex) {
    System.out.println("=====Service通知结束=====");
    //记录本地异常日志
    logger.error("==异常通知异常==");
    logger.error("异常信息:{}", ex.getMessage());
    }
    /*==========记录本地异常日志==========*/
    logger.error("异常方法:{}异常代码:{}异常信息:{}参数:{}", joinPoint.getTarget().getClass().getName() + joinPoint.getSignature().getName(), e.getClass().getName(), e.getMessage(), params);

    }


    /**
    * 获取注解中对方法的描述信息 用于service层注解
    *
    * @param joinPoint 切点
    * @return 方法描述
    * @throws Exception
    */
    public static String getServiceMthodDescription(JoinPoint joinPoint)
    throws Exception {
    String targetName = joinPoint.getTarget().getClass().getName();
    String methodName = joinPoint.getSignature().getName();
    Object[] arguments = joinPoint.getArgs();
    Class targetClass = Class.forName(targetName);
    Method[] methods = targetClass.getMethods();
    String description = "";
    for (Method method : methods) {
    if (method.getName().equals(methodName)) {
    Class[] clazzs = method.getParameterTypes();
    if (clazzs.length == arguments.length) {
    description = method.getAnnotation(SystemServiceLog. class).description();
    break;
    }
    }
    }
    return description;
    }

    /**
    * 获取注解中对方法的描述信息 用于Controller层注解
    *@SystemControllerLog(description = "用户登录") 该方法获取描述部分
        * @param joinPoint 切点
    * @return 方法描述
    * @throws Exception
    */
    public static String getControllerMethodDescription(JoinPoint joinPoint) throws Exception {
    String targetName = joinPoint.getTarget().getClass().getName();
    String methodName = joinPoint.getSignature().getName();
    Object[] arguments = joinPoint.getArgs();
    Class targetClass = Class.forName(targetName);
    Method[] methods = targetClass.getMethods();
    String description = "";
    for (Method method : methods) {
    if (method.getName().equals(methodName)) {
    Class[] clazzs = method.getParameterTypes();
    if (clazzs.length == arguments.length) {
    description = method.getAnnotation(SystemControllerLog. class).description();
    break;
    }
    }
    }
    return description;
    }
    }
    ----------------------------------------------------------------------------------------------------------------------------------------
    xml配置支持
    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:p="http://www.springframework.org/schema/p" xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context-4.0.xsd
    http://www.springframework.org/schema/aop
    http://www.springframework.org/schema/aop/spring-aop-3.1.xsd
    http://www.springframework.org/schema/mvc
    http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd">
    <!--划红线的为配置aop必须的xml文件头 -->

    <aop:aspectj-autoproxy/> <!--这行对aop配置至关重要,且必须放在spring-mvc配置文件中方可生效 -->
    <!-- 自动扫描(自动注入) -->
    <context:component-scan base-package="cn.cjq.controller;cn.cjq.api;"/>
    <mvc:annotation-driven  /><!-- cache-period="315360000" -->
    --------------------------------------------------------------------------------------------------------
    实例:Controller前置拦截
    /**
    * 用户登录
    */
    @ResponseBody()
    @RequestMapping(value = "userLogin")
    @SystemControllerLog(description = "用户登录")
    public Object userLogin(
    @RequestParam(value="userName",required=false,defaultValue="") String userName,
    @RequestParam(value="passWord",required=false,defaultValue="") String passWord,
    @RequestParam(value="rememberMe",required=false,defaultValue="0") boolean rememberMe,
    @RequestParam(value="validateCode",required=false,defaultValue="") String validateCode,
    @RequestParam(value="userType",required=false,defaultValue="") String userType
    ) throws Exception{
    String error=null;
    Subject subject = SecurityUtils.getSubject();
    UsernamePasswordToken token = new UsernamePasswordToken(userName, passWord,rememberMe);
    try {
    subject.login(token);
    //如何能够访问到已经在 Realm 中获取到的 User 的实例.
    //Object principal = SecurityUtils.getSubject().getPrincipals().getPrimaryPrincipal();

    } catch (UnknownAccountException e) {
    error = "用户名/密码错误";
    } catch (IncorrectCredentialsException e) {
    error = "用户名/密码错误";
    } catch (AuthenticationException e) {
    //其他错误,比如锁定,如果想单独处理请单独catch处理
    error = "其他错误:" + e.getMessage();
    }
    Map<Object, Object> result = new HashMap<Object, Object>();
    if(error != null ){
    result.put("success", false);
    result.put("message", error);
    }else{
    User user = userServiceImpl.findByUserName(userName);
    Session sessions = subject.getSession();
    sessions.setAttribute("user",user );
    result.put("success", true);
    }
    return result;
    }
    实例2:service异常拦截
    /**
    * 根据用户名查询账号信息
    */
    @SystemServiceLog(description = "查询账号信息异常")
    public User findByUserName (String username)throws Exception{

    User user = new User();

    List<User> accList = userMapper.findByUserName(username);
    if(accList.size()>0){
    user = accList.get(0);
    }else{
    user = null;
    }
    return user;
    }


    当能力支撑不了野心时,就该静下心来学习!
  • 相关阅读:
    技术分享会之——智能指针
    TeleMCU技术规格
    Golang-interface(一 基本使用)
    关于Mac虚拟机中安装的Windows系统键盘问题
    Android 高速开发系列 打造万能的ListView GridView 适配器
    [Erlang]怎样在Erlang中使用SSL
    Web最新力作有奖试读获奖名单发布
    每天复习Shell—ls
    Mininet系列实验(七):Mininet脚本实现控制交换机行为
    Mininet系列实验(七):Mininet脚本实现控制交换机行为
  • 原文地址:https://www.cnblogs.com/1234cjq/p/7908764.html
Copyright © 2011-2022 走看看