场景介绍
对标注了特定的自定义注解方法,在进入方法前会进行一些操作来获取特定的参数,这些参数可以放进上下文中,在业务逻辑代码中可以从上下文直接获取。
案例一:实现HandlerInterceptor
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface InjectAppId {
}
public class AppIdInjectInterceptor2 implements HandlerInterceptor {
public static Logger LOGGER = TrussLoggerFactory.getLogger(AppIdInjectInterceptor2.class);
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
LOGGER.info("AppIdInjectInterceptor is start");
HandlerMethod handlerMethod = (HandlerMethod) handler;
InjectAppId injectAppId = handlerMethod.getMethod().getAnnotation(InjectAppId.class);
if (injectAppId == null) {
// 直接通过
return true;
}
// 有InjectAppId注解,将AppId注入上下文后通过
Optional<AccountInfoBean> accountInfoBean = JwtUtils.getAccountInfoBean(request.getHeader("authorization"));
if (!accountInfoBean.isPresent()) {
LOGGER.error("JwtUtils parsing token failure.");
throw new CommonStorageException(CommonErrorCode.JWTUTILS_ANALYSIS_TOKEN_ERROR);
}
String appId = accountInfoBean.get().getProject();
LOGGER.info("AppId is :{}", appId);
IRequestContext requestContext = RequestContext.getCurrent();
requestContext.setItem("appId", appId);
return true;
}
}
@Configuration
public class MyInterceptorConfigurer implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new AppIdInjectInterceptor2());
}
}
案例二:实现MethodInterceptor(配置类)
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface InjectAppId {
}
@Named
public class AppIdInjectInterceptor implements MethodInterceptor {
public static Logger LOGGER = TrussLoggerFactory.getLogger(AppIdInjectInterceptor.class);
@Override
public Object invoke(MethodInvocation invocation) throws Throwable {
LOGGER.info("AppIdInjectInterceptor is start");
InjectAppId injectAppId = this.getInjectAppId(invocation);
if (injectAppId == null) {
return invocation.proceed();
}
LOGGER.info("The current method annotation is {}:", injectAppId);
doInjectAppId();
return invocation.proceed();
}
/**
* 往上下文注入AppId
*/
private void doInjectAppId() throws CommonStorageException {
LOGGER.info("doInjectAppId is start");
// 获取AppId
ServletRequestAttributes requestAttributes =
(ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
if (requestAttributes == null) {
LOGGER.error("Get httpRequest failure.");
throw new CommonStorageException(CommonErrorCode.HTTP_REQUEST_ERROR);
}
HttpServletRequest request = requestAttributes.getRequest();
Optional<AccountInfoBean> accountInfoBean = JwtUtils.getAccountInfoBean(request.getHeader("authorization"));
if (!accountInfoBean.isPresent()) {
LOGGER.error("JwtUtils parsing token failure.");
throw new CommonStorageException(CommonErrorCode.JWTUTILS_ANALYSIS_TOKEN_ERROR);
}
String appId = accountInfoBean.get().getProject();
LOGGER.info("AppId is :{}", appId);
// 放入上下文中
IRequestContext requestContext = RequestContext.getCurrent();
requestContext.setItem("appId", appId);
}
/**
* 获取InjectAppId注解类
*
* @param invocation invocation
* @return InjectAppId
*/
private InjectAppId getInjectAppId(MethodInvocation invocation) {
Method method = invocation.getMethod();
method = ClassUtils.getMostSpecificMethod(method, invocation.getThis().getClass());
return method.getAnnotation(InjectAppId.class);
}
}
@Configuration
public class InterceptorConfig {
public static final String traceAnnotationExecution =
"@annotation(com.hihonor.it.hcc.storage.common.annotation.InjectAppId)";
@Bean
public DefaultPointcutAdvisor appIdPointcutAdvisor() {
AppIdInjectInterceptor appIdInjectInterceptor = new AppIdInjectInterceptor();
DefaultPointcutAdvisor advisor = new DefaultPointcutAdvisor();
AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();
pointcut.setExpression(traceAnnotationExecution);
advisor.setPointcut(pointcut);
advisor.setAdvice(appIdInjectInterceptor);
return advisor;
}
}
案例三:实现MethodInterceptor(applicationContext.xml文件)
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface InjectAppId {
}
@Named
public class AppIdInjectInterceptor implements MethodInterceptor {
public static Logger LOGGER = TrussLoggerFactory.getLogger(AppIdInjectInterceptor.class);
@Override
public Object invoke(MethodInvocation invocation) throws Throwable {
LOGGER.info("AppIdInjectInterceptor is start");
InjectAppId injectAppId = this.getInjectAppId(invocation);
if (injectAppId == null) {
return invocation.proceed();
}
LOGGER.info("The current method annotation is {}:", injectAppId);
doInjectAppId();
return invocation.proceed();
}
/**
* 往上下文注入租户AppId
*/
private void doInjectAppId() throws CommonStorageException {
LOGGER.info("doInjectAppId is start");
// 获取AppId
ServletRequestAttributes requestAttributes =
(ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
if (requestAttributes == null) {
LOGGER.error("Get httpRequest failure.");
throw new CommonStorageException(CommonErrorCode.HTTP_REQUEST_ERROR);
}
HttpServletRequest request = requestAttributes.getRequest();
Optional<AccountInfoBean> accountInfoBean = JwtUtils.getAccountInfoBean(request.getHeader("authorization"));
if (!accountInfoBean.isPresent()) {
LOGGER.error("JwtUtils parsing token failure.");
throw new CommonStorageException(CommonErrorCode.JWTUTILS_ANALYSIS_TOKEN_ERROR);
}
String appId = accountInfoBean.get().getProject();
LOGGER.info("AppId is :{}", appId);
// 放入上下文中
IRequestContext requestContext = RequestContext.getCurrent();
requestContext.setItem("appId", appId);
}
/**
* 获取InjectAppId注解类
*
* @param invocation invocation
* @return InjectAppId
*/
private InjectAppId getInjectAppId(MethodInvocation invocation) {
Method method = invocation.getMethod();
method = ClassUtils.getMostSpecificMethod(method, invocation.getThis().getClass());
return method.getAnnotation(InjectAppId.class);
}
}
applicationContext.xml文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.1.xsd" default-lazy-init="true">
<beans>
<aop:config>
<aop:advisor advice-ref="programItemsInjectInterceptor" order="60"
pointcut="(execution(@com.nxq.it.common.annotation.InjectProgramItems * com.nxq..*Service.*(..))) or (execution(@com.nxq.it.common.annotation.InjectProgramItems * com.nxq..*Servlet.*(..)))"/>
</aop:config>
</beans>
</beans>