请求路由到业务方法设计(2)
扯淡:
看到首页又来一个C#和java争论,我也是蛮醉的,玩C#好的同学多得是,一个技术能全通所有技术是不可能,术业本来就是有专攻,即使能借鉴那也是比较有高度的概念借鉴而已。
而语言这种东西要分高低,我觉得是件很愚蠢的事。如果你真的想讨论,建议你写个万字级别的文章来论述,我想这样的话等你写完你也一定成长了不少。总之一个告诫,别做无益处无乐趣却太浪费时间的事情。
我自己玩java,主要也是喜欢 开源 这两个字。看得到更多别人想法的实现细节对于我这种个性的开发是一件蛮兴奋的事情。而我想喜欢C#的同学自有自己的乐趣所在。
主题:
上一篇文章地址:请求路由到业务方法设计(1)
@Target({ElementType. TYPE})@Retention(RetentionPolicy.RUNTIME )@Documented@Servicepublic @interface OpenServiceBean {}
第二个注解标识方法,那么这个路由map就是指定到方法的,这里可以注意到这个标签就是method字段,那么前端传过来的值中有这个字段:
@Target({ElementType. TYPE})@Retention(RetentionPolicy.RUNTIME )@Documentedpublic @interface OpenServiceMethod { /** * 服务的方法名,即由method参数指定的服务方法名 * */ String method() default ""; /** * 服务的中文名称 * */ String title() default "";}
接下来就是启动的时候解析,那些写着这些注解的类和方法了,然后缓存到map中。
public interface OpenServiceRouter { // 统一入口接口 public JSON doService(JSONObject json);}
下面是实现类,这个类是启动类:
// 实现,利用spring,实例化bean后,执行afterPropertiesSet()方法。// 而所有使用了注解的bean,都会被spring初始化好,也就是说,我们建立路由Map的时候,spring的容器已经准备好了,// 那么我们就可以去容器里拿这些bean来用了,所以此时我们必须先拿到ApplicationContext对象。所以使用了ApplicationContextAware。@Servicepublic class OpenServiceRouterImpl implements InitializingBean, OpenServiceRouter, ApplicationContextAware{ private Map<String, ServiceMethodHandler> routerMap; private OpenServiceContext context; private AbstractBaseServiceAdapter serviceAdapter; private ApplicationContext applicationContext; @Override public void afterPropertiesSet() throws Exception { // 执行器 this.serviceAdapter = new AbstractBaseServiceAdapter(); // 产生路由Map,具体看OpenServiceContext this.context = new OpenServiceContext(applicationContext); this.routerMap = this.context.getHandlerMap(); } @Override public JSON doService(JSONObject json) { // 根据method拿出指定的handler ServiceMethodHandler handler = routerMap.get(json.getString("method")); if(handler == null){ return new JSONObject();//TODO } // 拿到执行handler,执行 return serviceAdapter.execute(json, handler); } @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { this.applicationContext = applicationContext; }}
ServiceMethodHandler 用来存放处理器,也就是那些业务逻辑类和方法,那个Map的value也就是这个:
public class ServiceMethodHandler { public Class<? extends OpenRequest> getRequestType() { return requestType; } public void setRequestType(Class<? extends OpenRequest> requestType) { this. requestType = requestType; } private Object handler; private Method handlerMethod; //处理方法的请求对象类 private Class<? extends OpenRequest> requestType = OpenRequest.class; public Object getHandler() { return handler; } public void setHandler(Object handler) { this. handler = handler; } public Method getHandlerMethod() { return handlerMethod; } public void setHandlerMethod(Method handlerMethod) { this. handlerMethod = handlerMethod; }}
OpenServiceContext用来实际启动时将那些注解的类全部解析成路由Map,也算核心代码,上面提到的ROP框架也是一样的做法,值得借鉴,以后自己想写个小框架可以用用。
public class OpenServiceContext{ private Map<String, ServiceMethodHandler> handlerMap = new HashMap<String, ServiceMethodHandler>(); private Set<String> methodNameSet = new HashSet<String>(); private ApplicationContext applicationContext; public OpenServiceContext(){ initContext( this. applicationContext); } public OpenServiceContext( final ApplicationContext context){ initContext(context); } public void addServiceMethodHandler(String methodName, ServiceMethodHandler serviceMethodHandler){ methodNameSet.add(methodName); handlerMap.put(methodName, serviceMethodHandler); } public boolean isValidMethod(String methodName){ return methodNameSet.contains(methodName); } public Map<String, ServiceMethodHandler> getHandlerMap(){ return handlerMap; } // 执行方法前需要将ApplicationContext准备好 public void initContext( final ApplicationContext context){ String[] beanNames = context.getBeanNamesForType(Object.class ); if(beanNames == null){ return; } for (final String beanName : beanNames) { Class<?> handlerType = context.getType(beanName); // 本方法是最后一个参数根据注解直接过滤出来的method,放入Map ReflectionUtils. doWithMethods(handlerType, new ReflectionUtils.MethodCallback() { public void doWith(Method method) throws IllegalArgumentException, IllegalAccessException { ReflectionUtils.makeAccessible(method); OpenServiceMethod serviceMethod = method.getAnnotation(OpenServiceMethod .class); ServiceMethodHandler serviceMethodHandler = new ServiceMethodHandler(); //1.set handler serviceMethodHandler.setHandler(context.getBean(beanName)); //handler serviceMethodHandler.setHandlerMethod(method); //handler'method if(!ClassUtils. isAssignable(OpenResponse.class, method.getReturnType())){ throw new OpenServiceException(method.getDeclaringClass().getName() + "." + method.getName() + "的返回参数必须是" + OpenResponse.class.getName()); } if (method.getParameterTypes().length > 1) {//handler method's parameter throw new OpenServiceException(method.getDeclaringClass().getName() + "." + method.getName() + "的入参只能是" + OpenRequest.class.getName() + "或无入参。" ); } else if (method.getParameterTypes().length == 1) { Class<?> paramType = method.getParameterTypes()[0]; if (!ClassUtils.isAssignable(OpenRequest. class, paramType)) { throw new OpenServiceException(method.getDeclaringClass().getName() + "." + method.getName() + "的入参必须是" + OpenRequest.class.getName()); } serviceMethodHandler.setRequestType((Class<? extends OpenRequest>)paramType); } else { throw new OpenServiceException(method.getDeclaringClass().getName() + "." + method.getName() + "无入参" ); } addServiceMethodHandler(serviceMethod.method(), serviceMethodHandler); } }, new ReflectionUtils.MethodFilter() { @Override public boolean matches(Method method) { return AnnotationUtils.findAnnotation(method, OpenServiceMethod. class) != null; } } ); } } }
接下来就是执行器来执行指定逻辑代码了,因为Map中放的是Method,执行需要进行反射:
public class AbstractBaseServiceAdapter { /** * json ==> OpenRequest * @param json * @param handler * @return */ public final OpenRequest decode(JSON json, ServiceMethodHandler handler){ Class<? extends OpenRequest> requestClass = handler.getRequestType(); ObjectMapper mapper = new ObjectMapper(); OpenRequest request = null; try { request = mapper.readValue(json.toJSONString(), requestClass); } catch (Exception e) { throw new OpenServiceException( "open decode had a exp json==>"+json , e); } return request; } /** * OpenResponse ==> json * @param response * @return */ public final JSON encode(OpenResponse response){ ObjectMapper mapper = new ObjectMapper(); // Convert object to JSON string JSON json = null; try { String j = mapper.writeValueAsString(response); json = JSON. parseObject(j); } catch (Exception e) { throw new OpenServiceException( "open encode had a exp response==>"+response.getClass() , e); } return json; } public final JSON execute(JSON json, ServiceMethodHandler handler) { OpenRequest request = this.decode(json, handler); handler.getHandler(); handler.getHandlerMethod(); OpenResponse response = null; try { // 执行器执行对应方法 response = (OpenResponse) handler.getHandlerMethod().invoke( handler.getHandler(), request); } catch (Exception e) { throw new OpenServiceException( "open invoke had a exp json"+json , e); } JSON retrunJson = this.encode(response); return retrunJson; }}
让我们继续前行
----------------------------------------------------------------------
努力不一定成功,但不努力肯定不会成功。