为方便使用,对Spring监听器,拦截器,myBatis拦截器做了一些简单的简化处理。如图:
一、Spring拦截器:
public class CommonMVCInterceptor implements HandlerInterceptor {
@Autowired(required = false)
List<EasyMvcInterceptor> interceptors;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
return doPreHandle(request, response, handler);
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
// 简单处理下后面的逻辑,用处不大
doAfterInterceptor();
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
// 简单处理下后面的逻辑,用处不大
doAfterInterceptor();
}
private boolean doPreHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
if (!neet2Interceptor(handler)) {
return true;
}
for (EasyMvcInterceptor interceptor : interceptors) {
boolean excuteSuccess = interceptor.doBusiness((HandlerMethod) handler, request, response);
if (!excuteSuccess) {
return false;
}
}
return true;
}
private void doAfterInterceptor() {
if (null != interceptors && interceptors.size() > 0) {
for (EasyMvcInterceptor interceptor : interceptors) {
interceptor.doAfterInterceptor();
}
}
}
private boolean neet2Interceptor(Object handler) {
return handler instanceof HandlerMethod && null != interceptors && interceptors.size() > 0;
}
}
public interface EasyMvcInterceptor {
default void doAfterInterceptor() {
}
default boolean doBusiness(HandlerMethod handlerMethod, HttpServletRequest request, HttpServletResponse response) {
return doBusiness(handlerMethod, request);
}
default boolean doBusiness(HandlerMethod handlerMethod, HttpServletRequest request) {
Method method = handlerMethod.getMethod();
return doBusiness(method, request);
}
default boolean doBusiness(Method method, HttpServletRequest request) {
return doBusiness(method, SystemUtils.getRequestParams(request));
}
default boolean doBusiness(Method method, Map<String, String> params) {
return true;
}
}
//配置类
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Bean
public CommonMVCInterceptor commonMVCInterceptor() {
return new CommonMVCInterceptor();
}
@Override
public void addInterceptors(InterceptorRegistry registry) {
// 限流拦截
InterceptorRegistration commonMVCInterceptor= registry.addInterceptor(commonMVCInterceptor());
commonMVCInterceptor.addPathPatterns("/**");
commonMVCInterceptor.excludePathPatterns( "/error/**", "uedit");
commonMVCInterceptor.order(1);
}
}
//限流拦截器
public class LimitInterceptor implements EasyMvcInterceptor {
@Override
public boolean doBusiness(Method method, HttpServletRequest request) {
Limiter limiter = method.getAnnotation(Limiter.class);
if (null != limiter) {
try {
String api = SystemUtils.getApiFromRequest(request);
String token = RedisRaterLimiter.acquireTokenFromBucket(api,limiter.limit(), limiter.timeout());
if (null == token) {
throw new LocalException("您的访问太过频繁");
}
} catch (Exception e) {
e.printStackTrace();
throw new LocalException("您的访问太过频繁");
}
}
return true;
}
}
好处:
1、Spring拦截器只用注册一次,
2、不用再去作HandlerMethod 类型转换类型判断。
3、方便扩展。
二、Spring容器刷新监听器
public class CommonSpringListener implements ApplicationListener<ContextRefreshedEvent> {
@Autowired(required = false)
List<EasySpringListener> easySpringListeners;
@Override
public void onApplicationEvent(ContextRefreshedEvent event) {
ApplicationContext applicationContext = event.getApplicationContext();
// 异步执行一些容器启动时的初始化工作
if (null != easySpringListeners && easySpringListeners.size() > 0) {
easySpringListeners.forEach((easySpringListener) -> {
easySpringListener.doSome(applicationContext);
});
}
}
}
public interface EasySpringListener {
public void doSome(ApplicationContext applicationContext);
}
使用示例,
public class DictUtils implements EasySpringListener {
@Override
public void doSome(ApplicationContext applicationContext) {
initDictionary();
}
对监听器只做了些简单的处理,不用每次去获取容器
三、MyBatis拦截器
@Intercepts({ @Signature(type = Executor.class, method = "update", args = { MappedStatement.class, Object.class }) })
@Component
@Slf4j
public class CommonSqlInterceptor implements Interceptor {
@Autowired
List<EasySqlInterceptor> interceptors;
@Override
public Object intercept(Invocation invocation) throws Throwable {
Object state = invocation.getArgs()[0];
Object paremModel = invocation.getArgs()[1];
if (!need2Interceptor(state ,paremModel )) {
return invocation.proceed();
}
MappedStatement ms = (MappedStatement) state;
// 处理执行前的逻辑
executorBeforeExecutor(ms, paremModel);
// 执行sql
Object proceed = invocation.proceed();
// 处理执行后的逻辑
executorAfterExecutor(ms, paremModel);
return proceed;
}
@Override
public Object plugin(Object target) {
return Plugin.wrap(target, this);
}
@Override
public void setProperties(Properties properties) {
}
private void executorBeforeExecutor(MappedStatement ms, Object paremModel) {
if (null != interceptors && interceptors.size() > 0) {
try {
interceptors.forEach(it -> it.doBusinessBeforeExecutor(ms, paremModel));
} catch (Exception e) {
// 不影响正常逻辑的使用
return;
}
}
}
private void executorAfterExecutor(MappedStatement ms, Object paremModel) {
if (null != interceptors && interceptors.size() > 0) {
try {
interceptors.forEach(it -> it.doBusinessAfterExecutor(ms, paremModel));
} catch (Exception e) {
// 不影响正常逻辑的使用
log.warn("处理sql执行后逻辑出错,错误类型={},错误消息={}", e.getClass(), e.getMessage());
return;
}
}
}
//只拦截对象,不拦截集合等参数
private boolean need2Interceptor(Object state, Object paremModel) {
boolean isMappedStatement = state instanceof MappedStatement;
if (!isMappedStatement) {
return false;
}
if (null == paremModel) {
return false;
}
boolean isMap = paremModel instanceof Map;
if (isMap) {
return false;
}
boolean isList = paremModel instanceof List;
if (isList) {
return false;
}
return true;
}
}
public interface EasySqlInterceptor {
default boolean condition() {
return true;
}
default boolean condition(String sqlId) {
return condition();
}
default boolean condition(MappedStatement ms, Object paremModel) {
return condition(ms.getId());
}
default void doBusinessBeforeExecutor(MappedStatement ms, Object paremModel) {
if (!condition(ms, paremModel)) {
return;
}
String msId = ms.getId();
if (isInsert(ms)) {
doBusinessBeforeInsert(msId, paremModel);
} else if (isUpdate(ms, paremModel)) {
doBusinessBeforeUpdate(msId, paremModel);
} else if (isDelete(ms, paremModel)) {
doBusinessBeforeDelete(msId, paremModel);
}
}
default void doBusinessBeforeInsert(String sqlId, Object paremModel) {
}
default void doBusinessBeforeUpdate(String sqlId, Object paremModel) {
}
default void doBusinessBeforeDelete(String sqlId, Object paremModel) {
}
// ------------------------------------------------------------------------------------------------------
default void doBusinessAfterExecutor(MappedStatement ms, Object paremModel) {
if (!condition()) {
return;
}
String msId = ms.getId();
if (isInsert(ms)) {
doBusinessAfterInsert(msId, paremModel);
} else if (isUpdate(ms, paremModel)) {
doBusinessAfterUpdate(msId, paremModel);
} else if (isDelete(ms, paremModel)) {
doBusinessAfterDelete(msId, paremModel);
}
}
default void doBusinessAfterInsert(String sqlId, Object paremModel) {
}
default void doBusinessAfterUpdate(String sqlId, Object paremModel) {
}
default void doBusinessAfterDelete(String sqlId, Object paremModel) {
}
public static boolean isInsert(MappedStatement ms) {
return ms.getSqlCommandType().equals(SqlCommandType.INSERT);
}
public static boolean isUpdate(MappedStatement ms, Object paremModel) {
return ms.getSqlCommandType().equals(SqlCommandType.UPDATE) && !isDelete(ms, paremModel);
}
public static boolean isDelete(MappedStatement ms, Object paremModel) {
// 是直接删除
boolean isDelete = ms.getSqlCommandType().equals(SqlCommandType.DELETE);
if (isDelete) {
return true;
}
// 是软删除
List<String> deleteFlag = Arrays.asList("delete", "softDelete");
boolean isSoftDelete = deleteFlag.stream().anyMatch(d -> ms.getId().indexOf(d) != -1);
if (isSoftDelete) {
return true;
}
// 是更新删除标误解
Object fieldValue = DrinReflectUtils.getFieldValue(paremModel, "delFlag");
return "1".equals(String.valueOf(fieldValue));
}
}
使用示例:
public interface PublicFieldHandler extends EasySqlInterceptor {
public String getFieldName();
public Object getDefaultValue(String type);
@Override
default void doBusinessBeforeInsert(String msId, Object paremModel) {
setValue(paremModel);
}
@Override
default void doBusinessBeforeUpdate(String msId, Object paremModel) {
setValue(paremModel, "updateBy", "updateDate");
}
default void setValue(Object object, String... names) {
for (String name : names) {
if (name.equals(getFieldName())) {
setValue(object);
break;
}
}
}
default void setValue(Object object) {
try {
Field field = object.getClass().getDeclaredField(getFieldName());
if (null == field) {
return;
}
field.setAccessible(true);
// 看下原来是否设置了值
Object oldValue = field.get(object);
if (isNotNull(oldValue)) {
return;
}
field.set(object, getDefaultValue(field.getType().getSimpleName()));
} catch (Exception e) {
}
}
}
public class UpdateDateFieldHandler implements PublicFieldHandler {
@Override
public String getFieldName() {
return “updateDate”;
}
@Override
public Object getDefaultValue(String type) {
FieldType valueOf = FieldType.valueOf(type);
switch (valueOf) {
case Long:
return System.currentTimeMillis();
default:
return new Date();
}
}
}