SpringBoot - 基于Annotation的AOP

背景:

最近项目中需要设置HTTP请求,允许跨域访问的设置:

      
response.setHeader("Access-Control-Allow-Credentials","true");
response.setHeader("Access-Control-Allow-Origin", "*"); // 设置可以跨域访问

问题:如果为每个请求接口都这么设置的话,将会产生大量重复代码,身为一个追求完美的工程师,这种代码将遭到严重的鄙视!

解决:

1.使用AOP;项目基于SpringBoot开发的,直接自定义一个Aspect类,使用注解:

@Aspect

2.自定义注解,配合@PointCut,可以优雅的实现切点入口。

@Target(ElementType.METHOD,ELment.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented

public @interface HttpClientAnnotation {
    String value() default "";
}

什么?你不到如何自定义注解?看这里

3.实现自定义AOP:

package com.msa.bee.data.api.aop;
import javax.servlet.http.HttpServletResponse;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
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;
/**
 * 用于设置http通信允许跨域访问
 * @author Leon
 */
@Aspect
@Component
public class HttpClientAspect {
     private static Logger log = LoggerFactory.getLogger(HttpClientAspect.class);
     
     
     @Pointcut("@within(com.msa.bee.data.api.aop.HttpClientAnnotation)")
     public void log() {
           
     }
     
     /**
      * 设置允许跨域访问
      * @param response
      */
     @Before("log()")
     public void responseSetting() {
           log.info("response setting...");
           ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
           HttpServletResponse response = attributes.getResponse();
           if(null != response) {
                response.setHeader("Access-Control-Allow-Credentials","true");
                response.setHeader("Access-Control-Allow-Origin", "*"); // 设置可以跨域访问
                response.setContentType("text/html");
                response.setHeader("content-type", "text/json;charset=UTF-8");
           }
           else {
                log.warn("responseSetting method not working.");
           }
     }
}

4.关于@PointCut切点的几种常见方式:

1).execution是使用最多的一种Pointcut表达式,其标准语法如下:
execution(modifiers-pattern? ret-type-pattern declaring-type-pattern? name-pattern(param-pattern) throws-pattern?)
exp:
execution(public * com.test..*.*(..))  解释:拦截com.test包及其子包下的所有的方法
execution("@annotation(com.leon.TestAnnotation)") 将拦截所有开启了TestAnnotation注解的方法
 
2).within是用来指定类型的,将拦截指定类型下所有的方法
exp:
within("com.leon.TestService")将拦截TestService下的所有方法
within("com.leon..*")将拦截com.leon及其子包下的所有方法
within("@annotation(com.leon.TestAnnotation)")将拦截所有开启TestAnnotation注解的类下面的方法
 
比起execution,这种方式是不是非常优雅?

还有一些其他的一些方式,可自行百度。

posted @ 2018-08-06 13:50  兵临奇点  阅读(297)  评论(0)    收藏  举报