国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

請求路由到業務方法設計(2)-我們到底能走多遠系列(45)

2019-11-14 15:10:16
字體:
來源:轉載
供稿:網友

請求路由到業務方法設計(2)

扯淡:

看到首頁又來一個C#和java爭論,我也是蠻醉的,玩C#好的同學多得是,一個技術能全通所有技術是不可能,術業本來就是有專攻,即使能借鑒那也是比較有高度的概念借鑒而已。

而語言這種東西要分高低,我覺得是件很愚蠢的事。如果你真的想討論,建議你寫個萬字級別的文章來論述,我想這樣的話等你寫完你也一定成長了不少。總之一個告誡,別做無益處無樂趣卻太浪費時間的事情。

我自己玩java,主要也是喜歡 開源 這兩個字。看得到更多別人想法的實現細節對于我這種個性的開發是一件蠻興奮的事情。而我想喜歡C#的同學自有自己的樂趣所在。

 

主題:

上一篇文章地址:請求路由到業務方法設計(1)

希望實現的功能在上一篇文章描述過了,參考這個ROP框架,是因為它也要解決這個問題,而且是java實現,可以參考。
我這邊是自己參考后實現了一個,實際ROP框架實現參考源碼,不過git上已經很久沒有維護了。
另外:個人覺得ROP是java web開發可以詳細閱讀的小框架,花不了太多時間,了解結構,用到的模式,都是很好的學習素材,因為不是很龐大,所以可以有一個全局觀。讀大的框架,經驗不夠的時候,容易迷失,而且東西學的反而少。
 
思路是這樣:核心我們要在應用啟動后,產生出一個路由Map,這個map維護請求中的某個值對應執行哪一個類的哪個方法,也就是對應著那一段業務邏輯。如此就可以把輸入組裝好,放進統一如有接口中,然后就會執行相應邏輯。
 
這里使用注解的方式,來標識出那些業務邏輯,也就是給實現的業務邏輯打上標簽,用于啟動時組裝出路由Map。
 
第一個注解標識類:
@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;     }}

 

至此結構代碼已經理清,具體還有method的輸入輸出,需要統一接口實現,以保證執行器代碼的統一。
 
總結:
 
1,這個方案的核心就是利用注解來組裝好這個路由Map,以及用反射的方式執行對應的方法。
2,另外Spring的確十分強大,很多封裝代碼可以被使用。學習java的應該深入進去挖寶。
 
 
 

讓我們繼續前行

----------------------------------------------------------------------

努力不一定成功,但不努力肯定不會成功。


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 株洲县| 福建省| 平顺县| 工布江达县| 喀喇沁旗| 上林县| 莫力| 玉山县| 郎溪县| 宜川县| 凤庆县| 竹溪县| 尼木县| 宜昌市| 常熟市| 略阳县| 濉溪县| 廊坊市| 杭锦后旗| 上高县| 自贡市| 新干县| 邵东县| 蓝田县| 贞丰县| 延庆县| 漯河市| 普兰店市| 新营市| 容城县| 涞水县| 威信县| 天气| 澄城县| 广州市| 五河县| 望都县| 贺兰县| 克山县| 上思县| 永兴县|