处理器拦截器详解——跟着开涛学SpringMVC 程序员,你还不会合理选择Filter、Interceptor、Aspect?html
同一个系统中不一样的接口,均可以分红几种独特的类型,好比某些接口都是作确认交易的,某些接口都是作结果交易的,咱们把这种类似性叫作接口的风格,如Rapping中的不一样风格(Style),因此咱们给那些具备相同风格的接口以声明注解的方式来肯定该接口的Style,而在对应的Style中有经过责任链的机制来控制通用业务代码的执行时机,两者结合起来就叫作风格链(Style Chains)。 java
首先提醒一点,咱们应该避免“滥用”风格链,以免出现责任链模式可能带来的负效应,如:git
自定义业务风格器自己就是基于SpringMVC的拦截器来进行扩展:程序员
StyleHandlerInterceptor
来实现拦截器各个钩子
的时机捕获Style
的注解,若是有则调用并执行Style
的chains
字段,安装不一样的钩子调用不一样的类IChain
集合,而且有顺序的规则
IChain
它抽出了3个接口,分别对应拦截器的3个方法,即:
package cn.jiiiiiin.business.style.validator;
import cn.jiiiiiin.mvc.common.exception.MVCException;
import cn.jiiiiiin.mvc.common.style.chain.annotaion.Validator;
import cn.jiiiiiin.mvc.common.style.chain.impl.IValidator;
import cn.jiiiiiin.mvc.common.utils.MVCUtil;
import cn.jiiiiiin.validate.code.ValidateCodeProcessor;
import cn.jiiiiiin.validate.code.ValidateCodeProcessorHolder;
import cn.jiiiiiin.validate.code.dict.ValidateCodeDict;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import lombok.AllArgsConstructor;
import lombok.val;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.ServletWebRequest;
/** * 验证码验证逻辑,直接配置在网关完成,当前类只是作一个{@link IValidator}的示例 * * @author jiiiiiin */
@Validator
@AllArgsConstructor
@Deprecated
public class BusImageCodeValidator implements IValidator {
/** * 系统中的校验码处理器 */
private final ValidateCodeProcessorHolder validateCodeProcessorHolder;
@Override
public boolean validate(HttpServletRequest request, HttpServletResponse response, Object handler) throws MVCException {
val imageCode = MVCUtil.getData(ValidateCodeDict.DEFAULT_PARAMETER_NAME_CODE_IMAGE);
ValidateCodeProcessor validateCodeProcessor;
if (StringUtils.isNotEmpty(imageCode)) {
validateCodeProcessor = validateCodeProcessorHolder.findValidateCodeProcessor("image");
} else {
validateCodeProcessor = validateCodeProcessorHolder.findValidateCodeProcessor("sms");
}
validateCodeProcessor.validate(new ServletWebRequest(request, response));
return true;
}
}
复制代码
上面实现了一个通用的图形验证码校验器,这一块代码实际上是能够被共用的,由于图形验证码须要在进入到控制器对于接口以前被执行,故咱们这里集成了IValidator
,定义完毕以后,咱们就能够在须要的地方使用它,如:web
@ApiOperation(value = "行内转帐结果", notes = "行内转帐结果", httpMethod = "POST")
@PostMapping("/account/transfer/inner/InnerTransfer/Submit")
// @ResStyle
@Style(chains = {BusImageCodeValidator.class})
public InnerTransferSubmitVo.Res innerTransferSubmit( @RequestBody @Validated InnerTransferSubmitVo.Req req) {
innerTransferSvc.innerTransferSubmit(req);
InnerTransferSubmitVo.Res res = ReflectUtil.newInstance(InnerTransferSubmitVo.Res.class);
return res;
}
复制代码
@Style(chains = {BusImageCodeValidator.class})
便可以在某一个接口,如行内转帐结果接口spring
能够看到上面有一行注释的代码@ResStyle
,咱们看看它作了什么:apache
@Documented
@Target({METHOD})
@Style
@Retention(RUNTIME)
public @interface ResStyle {
Class<? extends IChain>[] chains() default {BusImageCodeValidator.class, BusLogCompletion.class};
}
复制代码
这是一个结果交易业务风格注解,在chains
中覆盖了@Style
注解的同名成员变量,在其中声明了一个图形验证码校验器,一个流水日志环绕记录器。 这样咱们就把结果交易须要完成的重复性业务代码给抽取出来了。mvc
最后咱们能够看到图形验证码校验器上面声明了一个@Validator
注解,它是什么? app
@Override
相似他们是一个语义化注解,在不一样的Bus Style实现组件上面表明这个类所要完成的工做,StyleHandlerInterceptor
中会以这一组注解为依据,调用@Style
中具备对应功能的组件集合的确切方法,也就是说若是你的组件implements IValidator
那么这个组件就必须声明成@Validator
组件,不然default boolean validate(HttpServletRequest request, HttpServletResponse response, Object handler)
接口将不会被执行,这也是为了经过强约束,来强化这种约定因为配置的设计。Interface
,如@Chain
->IChain
#Component
,这样的好处就是,被咱们的风格链注解注释的组件,都会默认加入到Spring的IOC
容器中系统中定义的类IChain
,每一个组件都须要更新到这里以便进行检索ide
组件 | 功能 | 模块 |
---|---|---|
验证码验证逻辑 | business-common |
系统中定义的类@Chain
,每一个注解都须要更新到这里以便进行检索
组件 | 功能 | 模块 |
---|---|---|
ResStyle | 结果交易通用注解 | business-common |