控制器服务上的多个连接(Spring)

时间:2014-07-07 16:35:15

标签: spring spring-mvc

我编写了一个控制器,它将域名作为输入,抓取整个站点并以JSON格式返回结果

http://crawlmysite-tgugnani.rhcloud.com/getUrlCrawlData/www.google.com

这会提供数据谷歌

http://crawlmysite-tgugnani.rhcloud.com/getUrlCrawlData/www.yahoo.com

这为雅虎提供了数据

如果我尝试同时运行这两个URL,我会看到我正在获取混合数据,并且其中一个的结果正在影响另一个,即使我尝试从不同的计算机中搜索它们。

这是我的控制器

@RequestMapping("/getUrlCrawlData/{domain:.+}")
@ResponseBody
 public String registerContact(@PathVariable("domain") String domain) throws       HttpStatusException, SQLException, IOException {
      List<URLdata> urldata = null;
    Gson gson = new Gson();
     String json;
     urldata = crawlService.crawlURL("http://"+domain);
     json = gson.toJson(urldata);
     return json;
 }

我需要做什么修改以允许多个独立连接。

更新

以下是我的抓取服务

public List<URLdata> crawlURL(String domain) throws HttpStatusException, SQLException, IOException{
    testDomain = domain;
    urlList.clear();
    urlMap.clear();
    urldata.clear();
    urlList.add(testDomain);
    processPage(testDomain);
    //Get all pages
    for(int i = 1; i < urlList.size(); i++){
        if(urlList.size()>=500){
            break;
        }
        processPage(urlList.get(i));
        //System.out.println(urlList.get(i));
    }
    //Calculate Time
    for(int i = 0; i < urlList.size(); i++){
        getTitleAndMeta(urlList.get(i));
    }
    return urldata;
}

public static void processPage(String URL) throws SQLException, IOException, HttpStatusException{

    //get useful information
try{

    Connection.Response response = Jsoup.connect(URL)
            .userAgent("Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/535.21 (KHTML, like Gecko) Chrome/19.0.1042.0 Safari/535.21")
            .timeout(10000)
            .execute();
    Document doc = response.parse();

    //get all links and recursively call the processPage method
    Elements questions = doc.select("a[href]");
    for(Element link: questions){
        String linkName = link.attr("abs:href");
        if(linkName.contains(testDomain.replaceAll("http://www.", ""))){
            if(linkName.contains("#")){
                linkName = linkName.substring(0, linkName.indexOf("#"));
            }
            if(linkName.contains("?")){
                linkName = linkName.substring(0, linkName.indexOf("?"));
            }
            if(!urlList.contains(linkName) && urlList.size() <= 500){

                urlList.add(linkName);
            }
        }
    }
}
catch(HttpStatusException e){
    System.out.println(e);
}
catch(SocketTimeoutException e){
    System.out.println(e);
}
catch(UnsupportedMimeTypeException e){
    System.out.println(e);
}
catch(UnknownHostException e){
    System.out.println(e);
}
catch(MalformedURLException e){
    System.out.println(e);
}
}

3 个答案:

答案 0 :(得分:2)

您的每个请求(http://crawlmysite-tgugnani.rhcloud.com/getUrlCrawlData/www.google.comhttp://crawlmysite-tgugnani.rhcloud.com/getUrlCrawlData/www.yahoo.com)都在一个单独的线程中处理。您有两个crawlURL()方法实例同时工作,但两种方法都使用相同的变量(testDomainurlListurlMapurldata)。所以他们把这些变量中的数据搞得一团糟。

解决问题的一种方法是在本地(在方法内)声明这些变量。这样,将为crawlURL()的每次调用创建这些变量的新实例。或者,您可以为CrawlService方法的每次调用创建crawlURL()类的新实例。

同步线程在这里是一个坏主意,因为一个请求将等待另一个请求完成,然后由crawlURL()处理。

答案 1 :(得分:1)

就SpringMVC而言,每个请求都在单独的线程中运行。所以我认为问题出现在crawlService中,我认为,这不是无国籍的(像单身一样)。尝试为每个请求创建新的抓取服务,并检查您的数据是否未混合。如果创建爬网服务是昂贵的操作,您应该重写它以无状态方式工作。

@RequestMapping("/getUrlCrawlData/{domain:.+}")
@ResponseBody
public String registerContact(@PathVariable("domain") String domain) throws HttpStatusException, SQLException, IOException {

    Gson gson = new Gson();
    List<URLdata> = new CrawlService().crawlURL("http://"+domain);
    return gson.toJson(urldata);
}

答案 2 :(得分:0)

我认为

urldata = crawlService.crawlURL("http://"+domain);

crawl Service来电是同时受Multiple requests影响的电话。

检查crawlService是否安全multithreading

即检查crawlURL()方法是synchronized,如果不是synchronized

synchronize the block内调用crawlservice

controller