zoukankan      html  css  js  c++  java
  • 请求类型分发处理机制

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

    当某一个项目需要各种各样的功能,比如有搜索,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;
    	}
    }
    

    总结:

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

  • 相关阅读:
    用 .Net WebBrowser 控件获取POST数据
    yield再理解--绝对够透彻
    Keras 和 PyTorch 的对比选择
    Keras -Python编写的开源人工神经网络库
    Python 加密之 生成pyd文件
    FPN全解-特征金字塔网络
    RetinaNet(Focal Loss)
    Focal Loss for Dense Object Detection(Retina Net)
    ImageNet Classification-darknet
    Darknet
  • 原文地址:https://www.cnblogs.com/bb-ben99/p/14025769.html
Copyright © 2011-2022 走看看