JSON

请求路由到业务方法设计(2)

字号+ 作者:H5之家 来源:H5之家 2015-11-10 14:41 我要评论( )

请求路由到业务方法设计(2) 扯淡: 看到首页又来一个C#和java争论,我也是蛮醉的,玩C#好的同学多得是,一个技术能全通所有技术是不可能,术业本来就

请求路由到业务方法设计(2) 扯淡:

看到首页又来一个C#和java争论,我也是蛮醉的,玩C#好的同学多得是,一个技术能全通所有技术是不可能,术业本来就是有专攻,即使能借鉴那也是比较有高度的概念借鉴而已。

而语言这种东西要分高低,我觉得是件很愚蠢的事。如果你真的想讨论,建议你写个万字级别的文章来论述,我想这样的话等你写完你也一定成长了不少。总之一个告诫,别做无益处无乐趣却太浪费时间的事情。

我自己玩java,主要也是喜欢 开源 这两个字。看得到更多别人想法的实现细节对于我这种个性的开发是一件蛮兴奋的事情。而我想喜欢C#的同学自有自己的乐趣所在。

主题:

上一篇文章地址: 请求路由到业务方法设计(1)

希望实现的功能在上一篇文章描述过了,参考这个ROP框架,是因为它也要解决这个问题,而且是java实现,可以参考。

我这边是自己参考后实现了一个,实际ROP框架实现参考源码,不过git上已经很久没有维护了。

另外:个人觉得ROP是java web开发可以详细阅读的小框架,花不了太多时间,了解结构,用到的模式,都是很好的学习素材,因为不是很庞大,所以可以有一个全局观。读大的框架,经验不够的时候,容易迷失,而且东西学的反而少。

思路是这样:核心我们要在应用启动后,产生出一个路由Map,这个map维护请求中的某个值对应执行哪一个类的哪个方法,也就是对应着那一段业务逻辑。如此就可以把输入组装好,放进统一如有接口中,然后就会执行相应逻辑。

这里使用注解的方式,来标识出那些业务逻辑,也就是给实现的业务逻辑打上标签,用于启动时组装出路由Map。

第一个注解标识类:

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

第二个注解标识方法,那么这个路由map就是指定到方法的,这里可以注意到这个标签就是method字段,那么前端传过来的值中有这个字段:

@Target({ElementType. TYPE}) @Retention(RetentionPolicy.RUNTIME ) @Documented public @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。@Service public 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; } } ); } } }

 

1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,请转载时务必注明文章作者和来源,不尊重原创的行为我们将追究责任;3.作者投稿可能会经我们编辑修改或补充。

相关文章
  • Windows 10开发基础

    Windows 10开发基础

    2015-11-24 18:58

  • 创建 REST API 的最佳入门教程

    创建 REST API 的最佳入门教程

    2015-11-23 17:25

  • 【Git 项目推荐】目前为止性能最强的 JSON 框架

    【Git 项目推荐】目前为止性能最强的 JSON 框架

    2015-11-21 13:18

  • Shunter - a Node.js application built to read JSON and trans

    Shunter - a Node.js application built to read JSON and trans

    2015-11-17 11:39

网友点评