服务热线

029-87595239

当前位置:首页 > 社区新闻 > 技术文章 >

Spring中aop的实践操作

之前用的ssm框架,大部分仅仅运用springIOC特性,很明显这能够为我们开发人员在目标的创立上面节约大部分时刻。当类似得到事务越来越多,许多代码也是越来越重复,轮子是越来越重复,比方验证用户登录这一块的代码。因为我们这边Java是给前端app调用的,在正式恳求事务接口的之前,会校验该用户是否登陆过。所以在每个 controller里边最开端都是校验前端传递的登录码是否有用。前几日得闲,想到springaop的特性,简略的了解就是拦截器,在恳求正式的事务数据之前,我们能够经过这个特性来验证客户端的是否现已登录(像今后如果比较复杂能够验证用户的的安排架构权限,过错日志收集等等)。事务场景就是这些,下面就是详细完成。

西安Java培训运用的是自界说注解来做的。首要界说一个切面注解,然后对这个注解添加声明解说,运用的盘绕通知,切面办法有详细的校验办法。最终依据自己的实际需要,在对应的办法上面加上这个切面注解。

1.spring.xmlspring-mvc.xml文件中添加aop支持

<!--启用AOP--><aop:aspectj-autoproxy />

2.声明切面注解

package cn.com.org.common.aspectAnnotation;

import java.lang.annotation.*;

/**

 * Created by kevin stark on 2017/7/12.

 */

@Target(ElementType.METHOD)

@Retention(RetentionPolicy.RUNTIME)

@Documentedpublic @interface AppTokenAspect {

    String methodName() default "";

3.对切面注解要做的操作的声明

package cn.com.org.control.aspectDefine;

import cn.com.org.common.constant.AllConstant;

import cn.com.org.service.user.service.UserBaseService;

import net.sf.json.JSONObject;

import org.aspectj.lang.ProceedingJoinPoint;

import org.aspectj.lang.annotation.Around;

import org.aspectj.lang.annotation.Aspect;

import org.aspectj.lang.annotation.Pointcut;

import org.slf4j.Logger;import org.slf4j.LoggerFactory;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.stereotype.Component;

import java.util.Date;import java.util.HashMap;

import java.util.Map;

/**

 * Created by kevin stark on 2017/7/12.

 * 定义具体的切面类

 */

@Aspect

@Componentpublic class APPTokenAspectDefine {

    private Logger log = LoggerFactory.getLogger(this.getClass());

    @Autowired

    private UserBaseService userBaseService;

    // 定义一个 Pointcut, 使用 切点表达式函数 来描述对哪些 Join point 使用 advise.

    @Pointcut("@annotation(cn.com.org.common.aspectAnnotation.AppTokenAspect)")

    public void pointCut() {}

    /**

     * 环绕通知调用切入方法。

     * 在正式调用业务方法前,校验参数(token是否过期)

     * @param pjp

     * @return

     */

    @Around("pointCut()")

    public Object checkAppToken(ProceedingJoinPoint pjp){

        log.info("");

        Object object = null;

        Object[] objs = pjp.getArgs();

        //AopUtils

        try {

            if (null != objs && objs.length > 0) {

                for (int i = 0; i < objs.length; i++) {

                    Object obj = objs[i];

                    // 接口的请求参数都是json类型,循环出来的值判断这个是不是json类型

                    if (obj instanceof JSONObject) {

                        JSONObject json = (JSONObject) objs[i];

                        //判断json结构中是否包含token字段

                        if (json.containsKey("token")) {

                            String token = json.getString("token");

                            Map<String, Object> map = new HashMap<>();

                            Boolean isSuccess = false;

                            Integer responseCode = -1;

                            String responseMsg = "";

                            HashMap<String, String> tokenResult = userBaseService.checkToken(token.trim());

                            if (!"success".equals(tokenResult.get("code"))) {

                                isSuccess = Boolean.FALSE;

                                responseCode = AllConstant.TOKEN_INVALID_CODE;

                                responseMsg = AllConstant.TOKEN_INVALID_MSG;

                                map.put("isSuccess", isSuccess);

                                map.put("responseCode", responseCode);

                                map.put("responseMsg", responseMsg);

                                return map;

                            } else {

                                // 可以对传参进行改造,比如校验通过后,就可以换到这个登录码对应的用户ID

                                json.put("empCode", tokenResult.get("userCode"));

                                objs[i] = json;

                            }

                        }

                    }

                }

            }

            //如果校验通过程序往下执行

            object =  pjp.proceed();

        } catch (Exception e) {

            e.printStackTrace();

        } catch (Throwable throwable) {

            throwable.printStackTrace();

        }
     // 因为我们拦截的方法都是有返回值的,智力要注意null的情况不然会报错,所以这里要做一点判空的处理

        if (null == object) {

            object = new Object();

        }

        return object;

    }

}

4.spring.xml中声明这个bean

<bean id="appTokenAspectDefine"

class="cn.com.bluemoon.control.aspectDefine.APPTokenAspectDefine"></bean>

具体应用

/**

     * .获取目录页ICON的角标数

     * @param request

     * @param jsonObject

     * @return

     */

    // 添加切面主键,当有请求访问这个方法的时候,会调用的切面里面的校验登录码的方法

    @AppTokenAspect

    @ResponseBody

    @RequestMapping(value="/getModel")

    public Map<String, Object> getModel(HttpServletRequest request, @RequestBody JSONObject jsonObject) {

}  
所以按照此办法在实践事务办法中,就可以节约更多的代码了。今后的日志手机或者说用户行为买点也可以按照此办法来改造了。