本文将从实际业务出发,展示一种业务请求分发处理实现机制。
当某一个项目需要各种各样的功能,比如有搜索,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;
}
}
总结:
本实现机制实现业务请求分发处理,具有易扩展、易维护、低耦合的特点