栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

记录一次对AOP的使用,使用AOP完成i18n多语言支持的集成

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

记录一次对AOP的使用,使用AOP完成i18n多语言支持的集成

上回说到


算了。不说了。。。。之前用增强Controller完成了有i18n的支持,后来想想,要不要试试用拦截器和aop各自实现一次试试,说干就干
首先准备了依赖

依赖

文章目录
  • 上回说到
      • 依赖
      • 定义一个切面
    • 完整代码
    • 关于切点和切点表达式
      • 切入点
      • 切点表达式
      • 切入点表达式详解

 
 
     org.springframework.boot
     spring-boot-starter-aop
 
 
     com.alibaba
     fastjson
     1.2.47
 
定义一个切面

我们使用@Aspect注解在类上将一个类定义为切面类,
使用@Pointcut(切面表达式)定义切入点
使用@Around(切入点)指定一个切面内容切入哪个切入点
方法有一个参数ProceedingJoinPoint pjp 这个就代表被切入的方法,我们可以使用pjp.proceed()使原方法执行,注意这里是使原方法执行,执行到这里就会直接执行原来的方法,如果有返回值可以直接获取;
如果不调用则不会执行原方法内容,调用了原方法之后,就会暂停在等待返回哪个阶段,,所以此时如果使用的使ResponseEntity响应的,并不会被解析为其中的泛型,返回值依然是ResponseEntity,不像增强Controller,获取到的object是解析后的泛型所指类型;
响应顺序…方法响应=>aop=>增强controller=>拦截器=>过滤器

完整代码


@Aspect  // 定义为一个切面
@Configuration
public class LogRecordAspect {

    private final ResultUtils resultUtils;

    public LogRecordAspect(ResultUtils resultUtils) {
        this.resultUtils = resultUtils;
    }

    private static final Logger logger = LoggerFactory.getLogger(LogRecordAspect.class);

    // 定义切点Pointcut
    @Pointcut("execution(public * com.doria.learnProject.codeStyle.LanguageMapper.*Controller.*(..))")
    public void resultPointcut() {
    }

    
    @Around("resultPointcut()") // 指定切面需要插入的切点
    public Object doAround(ProceedingJoinPoint pjp) throws Throwable {
        // 获取当前线程所绑定的requestAttributes
        RequestAttributes ra = RequestContextHolder.getRequestAttributes();
        // 强转以获取Request
        ServletRequestAttributes sra = (ServletRequestAttributes) ra;
        // 获取request[其实看到这个demo我也很疑惑为什么不直接拿去注入的HttpServletRequest,但是我很菜,不敢怀疑,听大佬的]
        assert sra != null;
        HttpServletRequest request = sra.getRequest();
        String method = request.getMethod();
        String uri = request.getRequestURI();
        String json = JSON.toJSONString(request.getParameterMap());
        logger.info("收到请求=>Uri:{},请求方式:{},参数:{}", uri, method, json);

        // 获取方法的返回值result的值就是返回值
        Object result = pjp.proceed();
        logger.info("请求结束=>返回值为:" + JSON.toJSONString(result));

        // 由于特殊需要,这里需要对参数的返回值进行处理,这里是吧code转为对应的语言填入msg
        if (result instanceof Result)
            // 调用语言转换方法,大概内容就是强转然后读取code然后通过i18n转换为msg写入msg
            return resultUtils.languageFormatToResult(result);
        return result;
    }
}

语言填充方法

@Autowired
private MessageSource messageSource;


public Object languageFormatToResult(Object o){
    // 由于调用方法前使用了instanceof确定了具体类型,我们这里可以直接强转
    Result result = (Result) o;
    // 强转以后取出code
    String key = result.getCode().toString();
    // 设置msg,用code作为key获取参数
    result.setMsg(messageSource.getMessage(key,null, LocaleContextHolder.getLocale()));
    return result;
}
关于切点和切点表达式 切入点

可以通过这个注解定义一个切入点,其中可以没内容

// 定义切点Pointcut
    @Pointcut("execution(public * com.doria.learnProject.codeStyle.LanguageMapper.*Controller.*(..))")
    public void resultPointcut() {
    }
切点表达式

由于Spring切面粒度最小是达到方法级别,而execution表达式可以用于明确指定方法返回类型,类名,方法名和参数名等与方法相关的部件,并且在Spring中,大部分需要使用AOP的业务场景也只需要达到方法级别即可,因而execution表达式的使用是最为广泛的。如下是execution表达式的语法:

execution(modifiers-pattern? ret-type-pattern declaring-type-pattern?name-pattern(param-pattern) throws-pattern?)

这里问号表示当前项可以有也可以没有,其中各项的语义如下:

modifiers-pattern:方法的可见性,如public,protected;
ret-type-pattern:方法的返回值类型,如int,void等;
declaring-type-pattern:方法所在类的全路径名,如com.spring.Aspect;
name-pattern:方法名类型,如buisinessService();
param-pattern:方法的参数类型,如java.lang.String;
throws-pattern:方法抛出的异常类型,如java.lang.Exception;

切入点表达式详解
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/345300.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号