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,这种方式是不是非常优雅?
还有一些其他的一些方式,可自行百度。

浙公网安备 33010602011771号