0 0

Http解析中的OCP设计模式问题5

问题描述:
目前现在实际场景是需要自定义Hadoop的InputFormat,需要对包含大量HTTP内容(包括HTTP包头和内容,用\r\n\r\n分隔每段HTTP)文件进行解析,其中的HTTP METHOD有GET、POST、PUT等等,只需要提取GET、POST、PUT三种方法的内容。格式如下:

引用
GET http://localhost:8080/tienda1/publico/anadir.jsp?id=2&nombre=Jam%F3n+Ib%E9rico&precio=85&cantidad=%27%3B+DROP+TABLE+usuarios%3B+SELECT+*+FROM+datos+WHERE+nombre+LIKE+%27%25&B1=A%F1adir+al+carrito HTTP/1.1
User-Agent: Mozilla/5.0 (compatible; Konqueror/3.5; Linux) KHTML/3.5.8 (like Gecko)
Pragma: no-cache
Cache-control: no-cache
Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5
Accept-Encoding: x-gzip, x-deflate, gzip, deflate
Accept-Charset: utf-8, utf-8;q=0.5, *;q=0.5
Accept-Language: en
Host: localhost:8080
Cookie: JSESSIONID=B92A8B48B9008CD29F622A994E0F650D
Connection: close


POST http://localhost:8080/tienda1/publico/anadir.jsp HTTP/1.1
User-Agent: Mozilla/5.0 (compatible; Konqueror/3.5; Linux) KHTML/3.5.8 (like Gecko)
Pragma: no-cache
Cache-control: no-cache
Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5
Accept-Encoding: x-gzip, x-deflate, gzip, deflate
Accept-Charset: utf-8, utf-8;q=0.5, *;q=0.5
Accept-Language: en
Host: localhost:8080
Cookie: JSESSIONID=AE29AEEBDE479D5E1A18B4108C8E3CE0
Content-Type: application/x-www-form-urlencoded
Connection: close
Content-Length: 146

id=2&nombre=Jam%F3n+Ib%E9rico&precio=85&cantidad=%27%3B+DROP+TABLE+usuarios%3B+SELECT+*+FROM+datos+WHERE+nombre+LIKE+%27%25&B1=A%F1adir+al+carrito

PUT http://localhost:8080/tienda1/publico/registro.jsp HTTP/1.1
User-Agent: Mozilla/5.0 (compatible; Konqueror/3.5; Linux) KHTML/3.5.8 (like Gecko)
Pragma: no-cache
Cache-control: no-cache
Accept:text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5
Accept-Encoding: x-gzip, x-deflate, gzip, deflate
Accept-Charset: utf-8, utf-8;q=0.5, *;q=0.5
Accept-Language: en
Host: localhost:9090
Cookie: JSESSIONID=2266B1AC9E10E859DA43028606239875
Content-Type: application/x-www-form-urlencoded
Connection: close
Content-Length: 252

modo=registro&login=armand&password=prusiato&nombre=Samia&apellidos=Catalayud+Mirabet&email=balademas.mareuil6%40enlanzarote.com.vc&dni=28178710F&direccion=C%2F+Cala%2C+9%2C+&ciudad=Mutxamel&cp=25332&provincia=Zaragoza&ntc=8608089924764976&B1=Registrar



如果不考虑OCP原则则直接一个类或者函数,里面用Scanner的hasNext()方法判断开始的Token是“GET”还是“POST”还是“PUT”,然后分别调用scanner根据每种情况(包括不是需要的三种方法的情况)分别去读取解析或者是跳过该行。

然而上述的这种方法,一来扩展性不好,可重用性为零。每个if语句里面可能包含大量代码,即使写到一个函数里面,扩展起来每次都得大量增加或者修改代码,耦合性过高。

于是考虑OCP原则(开放封闭原则)和SRP原则(单一职责原则),设计一个HTTPLoader的接口
public  interface HttpLoader {

public  String loadRequest() throws IOException;

public boolean tryLoad();
}

然后设计了一个AbstractHttpFileLoader的抽象类
public abstract class AbstractHttpFileLoader implements HttpLoader{

public InputStream in;
private Scanner mScanner;
private Pattern Delim;

public AbstractHttpFileLoader(InputStream in){
this.in = in;
mScanner = new Scanner(in);
}

public String next(){
return mScanner.next();
}
public boolean hasNext(){
return mScanner.hasNext();

}
protected boolean hasNext(String pattern){
return mScanner.hasNext(pattern);
}

public void setDelim(Pattern p){
Delim = p;
mScanner.useDelimiter(Delim);
}

public void reset(){
mScanner.reset();
}


public void setScanner(Scanner scanner){
mScanner = scanner;
}


}


然后分别设计各个方法的处理类,HttpGetLoader、HttpPostLoader、HttpPutLoader,继承AbstractHttpFileLoader并实现HttpLoader接口。

看起来好像比较可行,但是Scanner扫描器读取的时候是将内容缓存到自身的一个buf变量中的,然后利用正则表达式去匹配。
因此,如果实例化HttpGetLoader后,tryLoad之后其实就已经读入一部分数据到buf,这样对应的inputstream的位置已经发生了变化。要使用HttpPostLoader去tryLoad的时候依然是还没被之前的Loader载入到buf前的位置开始的数据,那么如果InputStream支持mark和reset,那么可以通过在开始所有的tryLoad之前mark,然后tryload里面先reset然后才真正开始调用scanner.hasNext方法探测。

while(end - pos >0){
     mark()
     if(getLoader.tryLoad()){ getloader.loadRequest()}
     else if(postLoader.tryLoad()){postLoader.loadRequest()}
     else if(putLoader.tryLoad()){putLoader.loadRequest()}
     else{
        LOG.warn("Unsupported method type");
   }
}

public boolean tryLoad(){
      in.reset()
      mScanner.hasNext("GET") //以GET为例
}


但是问题是现在实际场景是需要自定义Hadoop的InputFormat,然后FSDataInputStream并不支持mark和reset,所以,能够想到的解决办法是给每个具体的HttpLoader例如HttpGetLoader增加setScanner和getScanner,然后每次判断一种情况后,getScanner,然后通过setScanner设置给下一个要判断的HttpLoader

while(end - pos>0){
     if(getloader.tryLoad()){ getloader.loadReqeust();continue;}
     scanner = getloader.getScanner();
     postloader.setScanner(scanner);

     if(postloader.tryLoad()){postloader.loadRequest();continue;}
     scanner = getloader.getScanner();
     putloader.setScanner(scanner);

     if(putloader.tryLoad()){putloader.loadRequest(); continue;}
     
     //其他情况
     LOG.warn("not supported");
}

感觉这样不是很好,不知道大家对于这个问题有什么新的设计思路,或者更加好的办法??
集思广益 ^ _ ^
2014年6月12日 23:11
目前还没有答案

相关推荐

    head设计模式+设计模式解析(第二版).rar

    《Head First 设计模式》与《设计模式解析(第二版)》是两本关于软件设计模式的重要书籍,它们深入浅出地介绍了设计模式这一核心编程概念。设计模式是经验丰富的软件开发人员在解决常见问题时所形成的通用解决方案...

    设计模式解析 第二版

    《设计模式解析 第二版》是一本深入探讨软件设计的经典教程,它涵盖了广泛的设计模式,旨在帮助开发者在面对复杂问题时能够优雅、高效地进行系统设计。设计模式是经验丰富的软件开发人员在解决常见问题时形成的最佳...

    Design Patterns Explained(设计模式解析英文版)

    ### 设计模式解析 #### 一、概述与背景 《设计模式解析》是一本深入浅出介绍设计模式的书籍,作者结合自身丰富的实践经验和教学经历,为读者提供了一个全面理解设计模式及其应用的方法论。该书荣获1999年第10届...

    研磨设计模式博文集

    设计模式是软件工程中的一种重要概念,它是在特定情境下为了解决常见问题而形成的一套最佳实践。这个“研磨设计模式博文集”显然是一份深入探讨设计模式的资料集合,其中可能包含了对多种设计模式的详细解析、示例...

    Java设计模式及案例

    Java设计模式是软件工程中的一种最佳实践,它提供了一种在特定情况下解决设计问题的通用模板。这些模式基于经验丰富的开发者的智慧,被广泛应用于创建可扩展、灵活且易于维护的代码。本资料《Java设计模式及案例》将...

    韩顺平_Java设计模式笔记.docx

    我们可以看到韩顺平老师的Java设计模式笔记涵盖了设计模式的基础概念、常见面试题解析、设计原则等内容,并通过具体案例来阐述设计模式的实际应用价值,旨在帮助学习者深刻理解并掌握设计模式,从而在实际工作中灵活...

    oracle11g ocp考试051详细解析

    为了帮助考生顺利通过考试,考试资料会提供详细解析和经验分享,不仅包括正确答案的解释,也有可能包含常见问题的汇总、易错点的提示以及一些复习技巧。通过这些资料,考生可以更好地理解Oracle SQL语言的各种用法,...

    设计模式 基于C#的工程化实现及扩展 王翔 pdf

    设计模式是软件工程中的重要概念,它是一种在特定场景下,为解决常见问题而形成的可复用的解决方案模板。在C#中,设计模式能够帮助开发者编写出更加灵活、可维护和可扩展的代码。王翔的这本书详细介绍了每一种模式的...

    Android源码设计模式解析与实战

    《Android源码设计模式解析与实战》是一本深入探讨Android系统源码中设计模式应用的专著。本书全面覆盖了面向对象设计的六大原则,包括单一职责原则、开放封闭原则、里氏替换原则、接口隔离原则、依赖倒置原则以及...

    HeadFirst设计模式

    通过对《HeadFirst设计模式》书中章节一的深入分析,我们不仅理解了设计模式的基本概念,还通过一个具体的例子学习了如何运用设计模式来解决实际问题。此外,我们还探讨了面向对象设计的原则及其在解决继承带来的...

    常见设计模式的解析和实现(C++)含源码

    本资源“常见设计模式的解析和实现(C++)”深入探讨了如何在C++中应用这些模式,以提高代码的可读性、可维护性和复用性。通过这个PDF文档,你可以了解到设计模式的基本概念以及它们在实际项目中的应用。 首先,我们...

    设计模式详解+源代码

    设计模式是软件工程中的一种最佳实践,用于解决在软件开发过程中常见的问题,提供了一套可重用的解决方案。本资源包含全套23种经典设计模式的详细解析,每种模式都配有详细的理论分析、实际应用案例以及Java源代码...

    设计模式Java版(英语)

    设计模式是软件工程中的一种最佳实践,它是在特定上下文中解决常见问题的模板,可以被重复使用,以创建高效、可维护的代码。在Java世界里,设计模式尤其重要,因为Java是一种广泛应用的企业级编程语言,对软件架构的...

    设计模式 Head First

    设计模式是软件工程中非常重要的一部分,它们代表了在特定场景下解决常见问题的最佳实践。通过学习和应用这些模式,开发人员可以构建出更加灵活、可扩展且易于维护的系统。《Head First 设计模式》这本书正是为此而...

    02-软件设计原则 模式深度解析和案例分析

    通过对软件设计原则和设计模式的深度解析,以及一系列应用策略的讲解,本课程旨在帮助软件工程师建立起良好的设计思维,并能够在实际工作中灵活运用各种设计模式。通过案例分析和实战演练,学员不仅可以学习到设计...

Global site tag (gtag.js) - Google Analytics