请求类型分发处理机制

本文将从实际业务出发,展示一种业务请求分发处理实现机制。

当某一个项目需要各种各样的功能,比如有搜索,sug,热点推荐,Es搜索这些功能时,这些功能对应不同的请求类型,不同的请求类型需要对应不同的处理方法,需要不同的拦截过滤器。本实现机制易于扩展,可以很方便的增加具体的处理类也就是一个个具体的功能,过滤器也可通过注解很方便的添加在各个具体的功能上。

首先来具体介绍下几个主要的接口以及类:

1.ApiRequestType:enum类型,定义多种请求类型
2.ApiDispatcher: 请求分发类
3.ApiHandler: 请求处理接口,定义方法handle(),getInterceptors()
4.AbstractApiHandler: 实现ApiHandler接口以及InitializingBean接口,服务启动自动扫描时添加拦截器
5.SearchDataHandler: 具体handler类,继承抽象类AbstractApiHandler,实现doHandle方法;注解方式标识该类需要的拦截器
6.ApiInteceptor: 拦截器接口,定义前置与后置处理方法

下面写上具体代码进行展示:

1.ApiRequestType : Enum类型,定义了请求类型,定义每一个请求对应的具体处理类handler ,当然也可以对每一个枚举定义一些额外的定制化项,比如返回项数据类型,以及缓存时机等,根据业务需求来。

public enum ApiRequestType {
	/**
	 *  热点推荐
	 */
	HOT_RECOMMAND("hotspot", HotDataHandler.class, HotRecommandItem.class, H_1),
	/**
	 *  根据关键字搜索
	 */
	SEARCH_BY_QUERY("search_by_query", SearchDataHandler.class, null, M_10);

	/**
	 *  请求类型
	 */
	private String type;
	/**
	 *  对应的处理器
	 */
	private Class<? extends ApiHandler> handlerClass;
	/**
	 *  返回项数据类型
	 */
	private Class<? extends BaseObj> itemClass;
    ...
}

2.ApiDispatcher:请求分发类,获取请求requestType对应的请求处理器,SpringContextUtil是自定义工具类,通过ApplicationContext来获取bean

@Slf4j
@Service
public class ApiDispatcher {

	/**
	 *  API Dispatcher
	 */
	public Object dispatch(ApiRequestType requestType, Long ucid, Object request, Converter converter) throws Exception{
		return toHandle(requestType, getApiHandler(requestType), ucid, request, converter);
	}

	/**
	 *  获取处理器
	 */
	public ApiHandler getApiHandler(ApiRequestType requestType) {
		Class<? extends ApiHandler> handlerClass = requestType.getHandlerClass();
		if (handlerClass == null) {
			// no handler class	
		}
        //获取bean
		ApiHandler apiHandler = SpringContextUtil.getBean(handlerClass);
		if (apiHandler == null) {
			// no handler bean
		}
		return apiHandler;
	}

	/**
	 *  业务处理
	 */
	public Object toHandle(ApiRequestType requestType, ApiHandler apiHandler , Long ucid, Object request, Converter converter) {
		if (ucid == null) {
			return null;
		}
		EhrUserDTO user = getUser(ucid);
		if (user == null) {
			return null;
		}
		//处理
		Object response = apiHandler.handle(new ApiRequest(requestType, user, request));
	
		if (converter != null) {
			response = converter.convertFrom(response);
		}
		return response;
	}
}

3.ApiHandler:抽象类实现的接口

public interface ApiHandler {
	/**
	 *  api handle
	 */
	ApiResponse handle(ApiRequest request);

	/**
	 *  get all interceptors of the handler
	 * @return
	 */
	List<ApiInterceptor> getInterceptors();
}

4.AbstractApiHandler:实现ApiHandler的两个方法;实现InitializingBean的afterPropertiesSet方法,服务启动时,具体handler类实例化时添加拦截器;进行具体handler类的doHandle方法前后进行拦截器的前后置方法;

@Slf4j
public abstract class AbstractApiHandler  implements ApiHandler,InitializingBean {

	private List<ApiInterceptor> interceptors;

	@Override
	public ApiResponse handle(ApiRequest request) {
		try {
			LOGGER.info("{} handle request={}", this.getClass().getSimpleName(), request);
			// pre handle
			if (!CollectionUtils.isEmpty(interceptors)) {
				for (ApiInterceptor interceptor : interceptors) {
					ApiResponse response = interceptor.preHandle(request, null);
					if (response != null) {
						return response;
					}
				}
			}

			// handle
			ApiResponse response = doHandle(request);
			// post handle
			if (!CollectionUtils.isEmpty(interceptors)) {
				for (ApiInterceptor interceptor : interceptors) {
					response = interceptor.postHandle(request, response, null);
				}
			}
			return response;
		} catch (Exception e) {
			LOGGER.info("{} handle request={} error", this.getClass().getSimpleName(), request, e);
		}
		return null;
	}

	protected abstract ApiResponse doHandle(ApiRequest request);

	/**
	 *  添加拦截器
	 *  两种方式:
	 *    1. Handler上加注解(@ApiInterceptors),服务启动时自动扫描;
	 *    2. 代码中手动添加;
	 * @param interceptor
	 */
	private void addInterceptor(ApiInterceptor interceptor) {
		if (interceptors == null) {
			interceptors = new ArrayList<>();
		}
		interceptors.add(interceptor);
	}

	@Override
	public List<ApiInterceptor> getInterceptors() {
		return interceptors;
	}

	@Override
	public void afterPropertiesSet() throws Exception {
		// 根据注解服务启动时自动添加拦截器,给各个具体非抽象类添加
		ApiInterceptors apiInterceptors = this.getClass().getAnnotation(ApiInterceptors.class);
		if (apiInterceptors != null && apiInterceptors.interceptorClasses().length > 0) {
			for (Class clazz : apiInterceptors.interceptorClasses()) {
				addInterceptor((ApiInterceptor) clazz.newInstance());
			}
		}
	}
}

5.SearchDataHandler具体处理类:注解标记该类需要添加的拦截器,可动态添加,且可实现拦截器前后置方法与核心方法解耦;实现AbstractApiHandler抽象类的doHandle方法,实现具体业务逻辑

@Slf4j
@Service
@ApiInterceptors(interceptorClasses = {RequestAuthInterceptor.class, DataAuthInterceptor.class, CacheInterceptor.class,
	PostInterceptor.class, DataFormatInterceptor.class})
public class SearchDataHandler extends AbstractApiHandler {
	@Override
	protected ApiResponse doHandle(ApiRequest request) {
		ApiResponse response = new ApiResponse(request.getRequestType());
		SearchResponse resp = null;
			// 根据关键字搜索
			resp = searchService.searchByQuery(...);
		response.setData(resp);
		return response;
	}
}

ApiInterceptors: 定义拦截器注解

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ApiInterceptors {

	Class[] interceptorClasses() default {};
}

6.ApiInterceptor:拦截器接口

public interface ApiInterceptor {
	/**
	 *  前置处理
	 */
	ApiResponse preHandle(ApiRequest request, Object handler);

	/**
	 *  后置处理
	 */
	ApiResponse postHandle(ApiRequest request, ApiResponse response, Object handler);
}


public class DataAuthInterceptor implements ApiInterceptor{
	@Override
	public ApiResponse preHandle(ApiRequest request, Object handler) {
		//前置处理
		return response;
	}

	@Override
	public ApiResponse postHandle(ApiRequest request, ApiResponse response, Object handler) {
		//后置处理
        return response;
	}
}

总结:

本实现机制实现业务请求分发处理,具有易扩展、易维护、低耦合的特点

posted @ 2020-11-23 17:37  一南瓜子  阅读(248)  评论(0编辑  收藏  举报