2012-01-12 65 views
3

對於分頁的目的,我們的UI傢伙指定的項目的範圍在HTTP頭中,如下所示:抓取從的HTTPHeader範圍內的值

Range: items=0-15 

在後續請求從web範圍可以是

Range: items=16-31 
Range: items=32-45 

...等...等

在我的控制器SearchRequestController.java,我試圖提取這些範圍,這樣我可以在發送到Solr的服務器在T返回值他通過設置起點和偏移量來請求卡盤。

我在做什麼如下(在SearchRequestController.java):

@RequestMapping("/billsSearch") 
@ResponseBody 
public SearchResult searchBills(HttpServletRequest request,@RequestBody SearchRequest searchRequest){ 
    String rangeRequest = request.getHeader("Range"); 
    //(1)Parse the rangeRequest using some mechanism 
    //(2)Set the start using the first value of the range 
    //(3) Add the second value to the start to get the offset 
    searchRequest.setStart(startValue); 
    searchRequest.setOffset(offsetValue); 
    return searchHelper(request,searchRequest); 
} 

有幾個問題,我有: 這是爲了要求在分塊的方式數據的最佳方式服務器?

如何提取請求頭中的範圍?

我假設request.getHeader("Range")將返回「items=16-31」。

正則表達式是從這個字符串中獲取16和31的最佳方式嗎?

如果我決定使用正則表達式,如果將範圍標題更改爲billItems = 16-31,表達式是否會中斷?

我是一個正則表達式n00b,所以很有可能我以錯誤的方式思考這個問題。

有沒有其他正則表達式來解析SpringMVC中的http頭這樣的範圍信息?

回答

2

這是從服務器以分塊方式請求數據的最佳方式嗎?

另一種方法是使用請求參數:

/billsSearch?from=15&to=31 

順便說一句,你可以使用@RequestHeader註釋:

public SearchResult searchBills(
     @RequestBody SearchRequest searchRequest, 
     @RequestHeader("Range") String range) { 
    //... 
} 

如何從請求中提取頭的範圍? [...]正則表達式是從這個字符串中獲取16和31的最佳方式嗎?

我將削減上-字符後"items="串,分裂和解析所得的兩個數值:

String[] ranges = range.substring("items=".length()).split("-"); 
int from = Integer.valueOf(ranges[0]); 
int to = Integer.valueOf(ranges[1]); 
1

兩個@RequestParameter和@RequestHeader參數是受試者類型轉換如果目標類型不是串。如果您有Range類型,則可以創建一個Converter <字符串,範圍>並將其註冊到conversionService。然後,你的控制器將看起來有點清潔:

public SearchResult searchBills(
      @RequestBody SearchRequest searchRequest, 
      @RequestHeader Range range) { 
     //... 
    } 

這將有用的,如果它常用於控制器發生。或者,如果它只是一個在控制器方法內進行解析的地方就足夠了。

1

簡單的範圍內首部解析器符合http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.35

class Range { 
    Integer start; 
    Integer end; 
    Integer suffixLength; 
} 

public class Main { 

    public static void main(String[] args) { 
     String input = "bytes=33-22,-333,20-,-55,43-0002"; 
     for (Range range : decodeRange(input)) { 
      if (range.suffixLength == null) { 
       System.out.printf("Range: %d->%s\n", range.start, range.end == null ? "enf of file" : range.end); 
      } else { 
       System.out.printf("Last %d bytes\n", range.suffixLength); 
      } 
     } 
    } 

    public static List<Range> decodeRange(String rangeHeader) { 
     List<Range> ranges = new ArrayList<>(); 
     String byteRangeSetRegex = "(((?<byteRangeSpec>(?<firstBytePos>\\d+)-(?<lastBytePos>\\d+)?)|(?<suffixByteRangeSpec>-(?<suffixLength>\\d+)))(,|$))"; 
     String byteRangesSpecifierRegex = "bytes=(?<byteRangeSet>" + byteRangeSetRegex + "{1,})"; 
     Pattern byteRangeSetPattern = Pattern.compile(byteRangeSetRegex); 
     Pattern byteRangesSpecifierPattern = Pattern.compile(byteRangesSpecifierRegex); 
     Matcher byteRangesSpecifierMatcher = byteRangesSpecifierPattern.matcher(rangeHeader); 
     if (byteRangesSpecifierMatcher.matches()) { 
      String byteRangeSet = byteRangesSpecifierMatcher.group("byteRangeSet"); 
      Matcher byteRangeSetMatcher = byteRangeSetPattern.matcher(byteRangeSet); 
      while (byteRangeSetMatcher.find()) { 
       Range range = new Range(); 
       if (byteRangeSetMatcher.group("byteRangeSpec") != null) { 
        String start = byteRangeSetMatcher.group("firstBytePos"); 
        String end = byteRangeSetMatcher.group("lastBytePos"); 
        range.start = Integer.valueOf(start); 
        range.end = end == null ? null : Integer.valueOf(end); 
       } else if (byteRangeSetMatcher.group("suffixByteRangeSpec") != null) { 
        range.suffixLength = Integer.valueOf(byteRangeSetMatcher.group("suffixLength")); 
       } else { 
        throw new RuntimeException("Invalid range header"); 
       } 
       ranges.add(range); 
      } 
     } else { 
      throw new RuntimeException("Invalid range header"); 
     } 
     return ranges; 
    } 
}; 

或者看看here