কীভাবে java.net. URL টি সংযোগ ব্যবহার করতে এবং এইচটিটিপি অনুরোধগুলিকে হ্যান্ডেল করতে হবে?


1945

ব্যবহার java.net.URLConnectionপ্রায়শই প্রায়শই এখানে জিজ্ঞাসা করা হয়, এবং ওরাকল টিউটোরিয়াল এটি সম্পর্কে খুব সংক্ষিপ্ত।

এই টিউটোরিয়ালটি মূলত কেবল একটি জিইটি অনুরোধটি ফায়ার করতে এবং প্রতিক্রিয়াটি কীভাবে পড়তে পারে তা দেখায়। এটি অন্যদের মধ্যে কীভাবে এটি কোনও পোষ্ট অনুরোধ সম্পাদন করে, অনুরোধ শিরোনাম সেট করে, প্রতিক্রিয়া শিরোনাম পড়তে পারে, কুকিজের সাথে ডিল করে, একটি এইচটিএমএল ফর্ম জমা দেয়, একটি ফাইল আপলোড করে, ইত্যাদি কীভাবে তা ব্যবহার করতে হয় তা কোথাও ব্যাখ্যা করে না

সুতরাং, আমি কীভাবে java.net.URLConnection"উন্নত" এইচটিটিপি অনুরোধগুলিকে গুলি করতে এবং পরিচালনা করতে ব্যবহার করব ?

উত্তর:


2711

আগে একটি দাবি অস্বীকার: পোস্ট কোড স্নিপেট সমস্ত মৌলিক উদাহরণ। আপনি তুচ্ছ হ্যান্ডেল করতে হবে IOExceptions এবং RuntimeExceptionমত গুলি NullPointerException, ArrayIndexOutOfBoundsExceptionএবং নিজেকে স্ত্রীদেরকে।


প্রস্তুতি

আমাদের প্রথমে কমপক্ষে ইউআরএল এবং চারসেটটি জানতে হবে। পরামিতিগুলি alচ্ছিক এবং কার্যকরী প্রয়োজনীয়তার উপর নির্ভর করে।

String url = "http://example.com";
String charset = "UTF-8";  // Or in Java 7 and later, use the constant: java.nio.charset.StandardCharsets.UTF_8.name()
String param1 = "value1";
String param2 = "value2";
// ...

String query = String.format("param1=%s&param2=%s", 
     URLEncoder.encode(param1, charset), 
     URLEncoder.encode(param2, charset));

ক্যোয়ারী প্যারামিটারগুলি অবশ্যই name=valueফর্ম্যাটে থাকতে হবে এবং এর সাথে সংযুক্ত হতে হবে &। আপনি সাধারণত চরসেটটি ব্যবহার করে ক্যোয়ারীর প্যারামিটারগুলি URL- এনকোড করে থাকবেন URLEncoder#encode()

এটি কেবল String#format()সুবিধার জন্য। আমি যখন স্ট্রিং কনকেনটেশন অপারেটরের প্রয়োজন হবে +তার চেয়ে বেশি পছন্দ করি ।


(বৈকল্পিক) ক্যোয়ারী প্যারামিটারগুলির সাথে একটি HTTP জিইটি অনুরোধ ফায়ার করা

এটি একটি তুচ্ছ কাজ। এটি ডিফল্ট অনুরোধ পদ্ধতি।

URLConnection connection = new URL(url + "?" + query).openConnection();
connection.setRequestProperty("Accept-Charset", charset);
InputStream response = connection.getInputStream();
// ...

যেকোন প্রশ্নের স্ট্রিংটি ব্যবহার করে ইউআরএলকে সংযুক্ত করা উচিত ?Accept-Charsetহেডার সার্ভার কি পরামিতি এনকোডিং রয়েছে প্রজ্ঞান পারে। যদি আপনি কোন কোয়েরি স্ট্রিং পাঠাবেন না থাকে, তাহলে আপনি চলে যাবে Accept-Charsetহেডার দূরে। আপনার যদি কোনও শিরোনাম সেট করার প্রয়োজন না হয় তবে আপনি URL#openStream()শর্টকাট পদ্ধতিটিও ব্যবহার করতে পারেন ।

InputStream response = new URL(url).openStream();
// ...

যেভাবেই হোক, অন্য দিকটি যদি একটি হয় HttpServletতবে এর doGet()পদ্ধতিটি কল করা হবে এবং পরামিতিগুলি উপলব্ধ হবে HttpServletRequest#getParameter()

পরীক্ষার উদ্দেশ্যে, আপনি নীচের মত প্রতিক্রিয়া বডি প্রসারিত করতে পারেন:

try (Scanner scanner = new Scanner(response)) {
    String responseBody = scanner.useDelimiter("\\A").next();
    System.out.println(responseBody);
}

ক্যোয়ারী পরামিতিগুলির সাথে একটি HTTP পোস্ট অনুরোধ ফায়ার করা

সেট URLConnection#setDoOutput()থেকে trueপরোক্ষভাবে পোষ্ট করতে অনুরোধ পদ্ধতি সেট করে। ওয়েব ফর্মগুলির মতো স্ট্যান্ডার্ড এইচটিটিপি পোস্টটি application/x-www-form-urlencodedসেই ধরণের যেখানে কোয়েরি স্ট্রিং রিকোয়েস্ট বডিতে লেখা থাকে।

URLConnection connection = new URL(url).openConnection();
connection.setDoOutput(true); // Triggers POST.
connection.setRequestProperty("Accept-Charset", charset);
connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded;charset=" + charset);

try (OutputStream output = connection.getOutputStream()) {
    output.write(query.getBytes(charset));
}

InputStream response = connection.getInputStream();
// ...

দ্রষ্টব্য: আপনি যখনই প্রোগ্রামটিমে কোনও এইচটিএমএল ফর্ম জমা দিতে চান, তখন name=valueকোনও <input type="hidden">উপাদানগুলির জোড়া ক্যোয়ারী স্ট্রিংয়ে নিতে অবশ্যই ভুলবেন না এবং অবশ্যই এর name=valueজোড়ও<input type="submit"> উপাদানটির যা আপনি প্রোগ্রামে "চাপতে" চান (কারণ) যেটি সাধারণত কোনও বোতাম টিপে থাকে এবং যদি তাই হয় তবে কোনটি আলাদা করতে সার্ভার সাইডে ব্যবহৃত হয়।

আপনি প্রাপ্তগুলি কাস্ট করতে পারেন এবং এর পরিবর্তে এটি ব্যবহার URLConnectionকরতে HttpURLConnectionপারেন HttpURLConnection#setRequestMethod()। আপনি যদি আউটপুটটির জন্য সংযোগটি ব্যবহার করার চেষ্টা করছেন তবে আপনাকে এখনও সেট আপ URLConnection#setDoOutput()করতে হবে true

HttpURLConnection httpConnection = (HttpURLConnection) new URL(url).openConnection();
httpConnection.setRequestMethod("POST");
// ...

যেভাবেই হোক, অন্য দিকটি যদি একটি হয় HttpServletতবে এর doPost()পদ্ধতিটি কল করা হবে এবং পরামিতিগুলি উপলব্ধ হবে HttpServletRequest#getParameter()


আসলে এইচটিটিপি অনুরোধ চালানো

আপনি এইচটিটিপি অনুরোধকে স্পষ্টভাবে ফায়ার করতে পারেন URLConnection#connect()তবে আপনি এইচটিটিপি প্রতিক্রিয়া সম্পর্কিত কোনও তথ্য পেতে চাইলে যেমন রেসপন্স বডি ব্যবহার করে ইত্যাদি অনুরোধটি স্বয়ংক্রিয়ভাবে চাহিদা অনুসারে বরখাস্ত হয়ে যাবে URLConnection#getInputStream()। উপরের উদাহরণগুলি হুবহু এটি করে, তাই connect()কলটি বাস্তবে অতিমাত্রায়।


HTTP প্রতিক্রিয়া তথ্য সংগ্রহ করা

  1. HTTP প্রতিক্রিয়া স্থিতি :

    তোমার HttpURLConnectionএখানে একটা দরকার প্রয়োজনে প্রথমে কাস্ট করুন।

    int status = httpConnection.getResponseCode();
  2. HTTP প্রতিক্রিয়া শিরোনাম :

    for (Entry<String, List<String>> header : connection.getHeaderFields().entrySet()) {
        System.out.println(header.getKey() + "=" + header.getValue());
    }
  3. HTTP প্রতিক্রিয়া এনকোডিং :

    যখন Content-Typeকোনও charsetপ্যারামিটার থাকে, তখন প্রতিক্রিয়া বডিটি সম্ভবত পাঠ্য ভিত্তিক হয় এবং আমরা তখন সার্ভার-পাশ নির্দিষ্ট বর্ণচিহ্ন এনকোডিং সহ প্রতিক্রিয়া বডিটি প্রক্রিয়া করতে চাই।

    String contentType = connection.getHeaderField("Content-Type");
    String charset = null;
    
    for (String param : contentType.replace(" ", "").split(";")) {
        if (param.startsWith("charset=")) {
            charset = param.split("=", 2)[1];
            break;
        }
    }
    
    if (charset != null) {
        try (BufferedReader reader = new BufferedReader(new InputStreamReader(response, charset))) {
            for (String line; (line = reader.readLine()) != null;) {
                // ... System.out.println(line) ?
            }
        }
    } else {
        // It's likely binary content, use InputStream/OutputStream.
    }

অধিবেশন রক্ষণ

সার্ভার সাইড সেশনটি সাধারণত একটি কুকি দ্বারা সমর্থনযুক্ত। কিছু ওয়েব ফর্মগুলির জন্য আপনাকে লগ ইন এবং / অথবা একটি সেশন দ্বারা ট্র্যাক করা দরকার। আপনি CookieHandlerকুকিজ বজায় রাখতে API ব্যবহার করতে পারেন । আপনি একটি প্রস্তুতির প্রয়োজন CookieManagerএকটি সঙ্গে CookiePolicyএর ACCEPT_ALLসব HTTP অনুরোধ পাঠানোর আগে।

// First set the default cookie manager.
CookieHandler.setDefault(new CookieManager(null, CookiePolicy.ACCEPT_ALL));

// All the following subsequent URLConnections will use the same cookie manager.
URLConnection connection = new URL(url).openConnection();
// ...

connection = new URL(url).openConnection();
// ...

connection = new URL(url).openConnection();
// ...

নোট করুন যে এটি সর্বদা সর্বদা সঠিকভাবে কাজ না করার জন্য পরিচিত। যদি এটি আপনার পক্ষে ব্যর্থ হয় তবে ম্যানুয়ালি কুকি শিরোনামগুলি সংগ্রহ করা এবং সেট করা ভাল। আপনাকে মূলত Set-Cookieলগইনের প্রতিক্রিয়া বা প্রথম GETঅনুরোধ থেকে সমস্ত শিরোনাম দখল করতে হবে এবং তারপরে পরবর্তী অনুরোধগুলির মাধ্যমে এটি পাস করতে হবে।

// Gather all cookies on the first request.
URLConnection connection = new URL(url).openConnection();
List<String> cookies = connection.getHeaderFields().get("Set-Cookie");
// ...

// Then use the same cookies on all subsequent requests.
connection = new URL(url).openConnection();
for (String cookie : cookies) {
    connection.addRequestProperty("Cookie", cookie.split(";", 2)[0]);
}
// ...

split(";", 2)[0]সেখানে কুকি বৈশিষ্ট্যাবলী যা মত সার্ভার প্রান্তের জন্য অপ্রাসঙ্গিক পরিত্রাণ পেতে হয় expires, pathইত্যাদি অন্যথা, আপনি ব্যবহার করতে পারে cookie.substring(0, cookie.indexOf(';'))পরিবর্তে split()


স্ট্রিমিং মোড

HttpURLConnectionডিফল্টরূপে ইচ্ছা বাফার সমগ্র সামনে আসলে এটি পাঠানোর আপনি একটি নির্দিষ্ট বিষয়বস্তু দৈর্ঘ্য নিজেকে ব্যবহার সেট করেছি কিনা নির্বিশেষে অনুরোধের মূল connection.setRequestProperty("Content-Length", contentLength);OutOfMemoryExceptionযখনই আপনি একযোগে বড় পোস্টের অনুরোধগুলি প্রেরণ করেন (যেমন ফাইল আপলোড করা) এটির কারণ হতে পারে । এটি এড়াতে, আপনি এটি সেট করতে চান HttpURLConnection#setFixedLengthStreamingMode()

httpConnection.setFixedLengthStreamingMode(contentLength);

তবে যদি সামগ্রীর দৈর্ঘ্যটি সত্যই আগে জানা থাকে না তবে আপনি সেই HttpURLConnection#setChunkedStreamingMode()অনুযায়ী সেট করে চুনযুক্ত স্ট্রিমিং মোডটি ব্যবহার করতে পারেন । এটি এইচটিটিপি Transfer-Encodingশিরোনাম সেট করবে chunkedযা অনুরোধের অংশটিকে অংশগুলিতে পাঠানো বাধ্য করবে। নীচের উদাহরণটি 1KB এর অংশগুলিতে দেহটি প্রেরণ করবে।

httpConnection.setChunkedStreamingMode(1024);

ব্যবহারিক দূত

এটি ঘটতে পারে যে কোনও অনুরোধটি একটি অপ্রত্যাশিত প্রতিক্রিয়া ফিরিয়ে দেয়, যখন এটি আসল ওয়েব ব্রাউজারের সাথে দুর্দান্ত কাজ করে । সার্ভার পক্ষটি সম্ভবত User-Agentঅনুরোধ শিরোনামের ভিত্তিতে অনুরোধগুলি অবরুদ্ধ করছে । URLConnectionডিফল্টরূপে করবে সেট Java/1.6.0_19যেখানে শেষ অংশ স্পষ্টত JRE সংস্করণ। আপনি নিম্নলিখিত হিসাবে এটি ওভাররাইড করতে পারেন:

connection.setRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2228.0 Safari/537.36"); // Do as if you're using Chrome 41 on Windows 7.

সাম্প্রতিক ব্রাউজার থেকে ব্যবহারকারী-এজেন্ট স্ট্রিংটি ব্যবহার করুন ।


ত্রুটি পরিচালনা

যদি HTTP প্রতিক্রিয়া কোডটি 4nn(ক্লায়েন্ট ত্রুটি) বা 5nn(সার্ভার ত্রুটি) হয় তবে HttpURLConnection#getErrorStream()সার্ভারটি কোনও কার্যকর ত্রুটির তথ্য প্রেরণ করেছে কিনা তা দেখতে আপনি পড়তে চাইতে পারেন।

InputStream error = ((HttpURLConnection) connection).getErrorStream();

যদি HTTP প্রতিক্রিয়া কোড -1 হয়, তবে সংযোগ এবং প্রতিক্রিয়া হ্যান্ডলিংয়ের সাথে কিছু ভুল হয়েছে। HttpURLConnectionবাস্তবায়ন সংযোগ জীবিত পালন কিছুটা বগী পুরোনো JREs হয়। আপনি http.keepAliveসিস্টেম বৈশিষ্ট্যটি সেট করে এটি বন্ধ করতে চাইতে পারেন false। আপনি আপনার অ্যাপ্লিকেশন শুরুতে এই প্রোগ্রামটিমেটিকভাবে করতে পারেন:

System.setProperty("http.keepAlive", "false");

ফাইল আপলোড হচ্ছে

আপনি সাধারণত multipart/form-dataমিশ্র পোস্টের সামগ্রী (বাইনারি এবং চরিত্রের ডেটা) জন্য এনকোডিং ব্যবহার করবেন। এনকোডিংটি আরএফসি 2388-এ বর্ণিত আরও বিশদে রয়েছে

String param = "value";
File textFile = new File("/path/to/file.txt");
File binaryFile = new File("/path/to/file.bin");
String boundary = Long.toHexString(System.currentTimeMillis()); // Just generate some unique random value.
String CRLF = "\r\n"; // Line separator required by multipart/form-data.
URLConnection connection = new URL(url).openConnection();
connection.setDoOutput(true);
connection.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + boundary);

try (
    OutputStream output = connection.getOutputStream();
    PrintWriter writer = new PrintWriter(new OutputStreamWriter(output, charset), true);
) {
    // Send normal param.
    writer.append("--" + boundary).append(CRLF);
    writer.append("Content-Disposition: form-data; name=\"param\"").append(CRLF);
    writer.append("Content-Type: text/plain; charset=" + charset).append(CRLF);
    writer.append(CRLF).append(param).append(CRLF).flush();

    // Send text file.
    writer.append("--" + boundary).append(CRLF);
    writer.append("Content-Disposition: form-data; name=\"textFile\"; filename=\"" + textFile.getName() + "\"").append(CRLF);
    writer.append("Content-Type: text/plain; charset=" + charset).append(CRLF); // Text file itself must be saved in this charset!
    writer.append(CRLF).flush();
    Files.copy(textFile.toPath(), output);
    output.flush(); // Important before continuing with writer!
    writer.append(CRLF).flush(); // CRLF is important! It indicates end of boundary.

    // Send binary file.
    writer.append("--" + boundary).append(CRLF);
    writer.append("Content-Disposition: form-data; name=\"binaryFile\"; filename=\"" + binaryFile.getName() + "\"").append(CRLF);
    writer.append("Content-Type: " + URLConnection.guessContentTypeFromName(binaryFile.getName())).append(CRLF);
    writer.append("Content-Transfer-Encoding: binary").append(CRLF);
    writer.append(CRLF).flush();
    Files.copy(binaryFile.toPath(), output);
    output.flush(); // Important before continuing with writer!
    writer.append(CRLF).flush(); // CRLF is important! It indicates end of boundary.

    // End of multipart/form-data.
    writer.append("--" + boundary + "--").append(CRLF).flush();
}

অন্য দিকটি যদি একটি হয় HttpServlet, তবে এর doPost()পদ্ধতিটি কল করা হবে এবং অংশগুলি উপলব্ধ থাকবে HttpServletRequest#getPart()(নোট, এভাবে নয় getParameter() এবং তাই!)। getPart()পদ্ধতি তবে অপেক্ষাকৃত নতুন, এটা সার্ভলেট 3.0 (গ্লাসফিস 3, হুল বিড়াল 7, ইত্যাদি) চালু নেই। Servlet 3.0 এর আগে, আপনার সেরা পছন্দটি একটি অনুরোধ পার্স করতে অ্যাপাচি কমন্স ফাইলআপলোড ব্যবহার করছে p ফাইল-আপলোড এবং সার্ভেল্ট 3.0.০ পদ্ধতির উভয়ের উদাহরণের জন্য এই উত্তরটিmultipart/form-data দেখুন ।


অবিশ্বস্ত বা ভুল কনফিগার করা এইচটিটিপিএস সাইটগুলির সাথে লেনদেন করা

কখনও কখনও আপনাকে এইচটিটিপিএস ইউআরএল সংযুক্ত করা দরকার, সম্ভবত আপনি ওয়েব স্ক্র্যাপ লিখেছেন। সেক্ষেত্রে আপনি সম্ভবত javax.net.ssl.SSLException: Not trusted server certificateকিছু এইচটিটিপিএস সাইটগুলির মুখোমুখি হতে পারেন যারা তাদের এসএসএল শংসাপত্রগুলি আপ টু ডেট রাখে না, বা একটি java.security.cert.CertificateException: No subject alternative DNS name matching [hostname] foundবা javax.net.ssl.SSLProtocolException: handshake alert: unrecognized_nameকিছু ভুল কনফিগার করা এইচটিটিপিএস সাইটগুলিতে।

staticআপনার ওয়েব স্ক্র্যাপার ক্লাসে নিম্নলিখিত এক-সময় পরিচালিত ইনিশিয়ালাইজারটি HttpsURLConnectionসেই এইচটিটিপিএস সাইটগুলিকে আরও হালকা করা উচিত এবং এইভাবে ব্যতিক্রমগুলি আর ছুঁড়ে দেওয়া উচিত নয়।

static {
    TrustManager[] trustAllCertificates = new TrustManager[] {
        new X509TrustManager() {
            @Override
            public X509Certificate[] getAcceptedIssuers() {
                return null; // Not relevant.
            }
            @Override
            public void checkClientTrusted(X509Certificate[] certs, String authType) {
                // Do nothing. Just allow them all.
            }
            @Override
            public void checkServerTrusted(X509Certificate[] certs, String authType) {
                // Do nothing. Just allow them all.
            }
        }
    };

    HostnameVerifier trustAllHostnames = new HostnameVerifier() {
        @Override
        public boolean verify(String hostname, SSLSession session) {
            return true; // Just allow them all.
        }
    };

    try {
        System.setProperty("jsse.enableSNIExtension", "false");
        SSLContext sc = SSLContext.getInstance("SSL");
        sc.init(null, trustAllCertificates, new SecureRandom());
        HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
        HttpsURLConnection.setDefaultHostnameVerifier(trustAllHostnames);
    }
    catch (GeneralSecurityException e) {
        throw new ExceptionInInitializerError(e);
    }
}

শেষ কথা

এ্যাপাচি HttpComponents HttpClient হয় অনেক MORE জনকে এই সব সুবিধাজনক :)


পার্সিং এবং এইচটিএমএল উত্তোলন

আপনি যদি চান সমস্তই এইচটিএমএল থেকে ডেটা পার্সিং এবং নিষ্কাশন করছে তবে জসুপের মতো এইচটিএমএল পার্সার আরও ভাল ব্যবহার করুন


119
আপনার আগে
অ্যাপাচি

40
@ আইভান্সরাস: যদি আপনি এই উত্তরের তথ্যের ভিত্তিতে এটিকে সিদ্ধ করতে না পারেন তবে দয়া করে Ask Questionডানদিকের উপরে বোতাম টিপুন ।
বালুস সি

3
@ ব্রাইস: অনুগ্রহ করে অনুগ্রহ করে পড়ুন। --অংশ সীমানা নিজেই অংশ নয়। এটি কেবল একটি বিভাজক স্ট্রিং। আমি আপনার অবৈধ সম্পাদনাটি ফিরিয়ে আছি।
বালুসসি

7
@ বালাসক এমন নিখুঁত টিউটোরিয়ালটির জন্য অনেক ধন্যবাদ। দয়া করে "সমাপ্তি স্ট্রিম / সংযোগগুলি" এর মতো শিরোনামও অন্তর্ভুক্ত করুন। কখন এবং কোন স্ট্রিম / সংযোগগুলি বন্ধ হবে সে সম্পর্কে আমি সত্যিই বিভ্রান্ত।

10
দুঃখের বিষয়টি হ'ল অ্যান্ড্রয়েডে এখন অ্যাপাচি ব্যবহার করার পরামর্শ দেওয়া হয়নি এবং নিষ্ঠুর। android-developers.blogspot.in/2011/09/…HttpClientHttpURLConnection
ইয়াতী সাগাদ

91

এইচটিটিপি নিয়ে কাজ করার HttpURLConnectionসময় বেস ক্লাসের চেয়ে উল্লেখ করা প্রায়শই সবসময় কার্যকর URLConnection(যেহেতু URLConnectionআপনি যখন URLConnection.openConnection()কোনও এইচটিটিপি ইউআরএলে জিজ্ঞাসা করেন তখন এটি একটি বিমূর্ত শ্রেণি যা আপনি যেভাবেই ফিরে পাবেন)।

তারপর আপনি যদি এর পরিবর্তে এর উপর নির্ভর করার পারেন URLConnection#setDoOutput(true)পরোক্ষভাবে অনুরোধ পদ্ধতি সেট করতে পোষ্ট পরিবর্তে কি httpURLConnection.setRequestMethod("POST")যা কিছু পেতে পারে আরো প্রাকৃতিক (এবং যা আপনি এই ধরনের অন্যান্য অনুরোধ পদ্ধতি নির্দিষ্ট করার অনুমতি দেবে PUT , মুছে দিন , ...)।

এটি দরকারী HTTP ধ্রুবকগুলি সরবরাহ করে যাতে আপনি এটি করতে পারেন:

int responseCode = httpURLConnection.getResponseCode();

if (responseCode == HttpURLConnection.HTTP_OK) {

1
setDoOutPut সত্য ছিল আমার সমস্যা যা আমার GET কে একটি পোস্টে সেট করে। ধন্যবাদ
প্যাট্রিক কাফকা

22
আপনি outputstream আপনি ডেটা লিখতে চেষ্টা করছেন আবশ্যক এখনও নির্ধারণ setDoOutput()করতে true(এমনকি যদি আপনি অন্যথায় একটি ব্যতিক্রম ফেলা হয় setRequestMethod("POST"))। স্পষ্ট হবে: সেটিং URLConnection#setDoOutput(true)থেকে trueপরোক্ষভাবে পোষ্ট করতে অনুরোধ পদ্ধতি সেট করে, কিন্তু সেটিং httpURLConnection.setRequestMethod("POST")পোস্টে নেই না পরোক্ষভাবে সেট setDoOutput()করতে true
টনি চ্যান 0

54

এটি এবং এসও সম্পর্কিত অন্যান্য প্রশ্নের দ্বারা অনুপ্রাণিত হয়ে, আমি একটি ন্যূনতম ওপেন সোর্স বেসিক-এইচ-পি-ক্লায়েন্ট তৈরি করেছি যা এখানে পাওয়া বেশিরভাগ কৌশল সজ্জিত করে।

Google এর HTTP জাভা-ক্লায়েন্ট একটি দুর্দান্ত ওপেন সোর্স রিসোর্স।


আমি ঠিক একই চিন্তা ছিল। তবে এটি এমন একটি বেয়ারবোন / সাধারণ জাভা লাইব্রেরিটি পেয়ে খুব ভাল লাগবে যা এখানে উপস্থাপিত হিসাবে কেবলমাত্র ইউআরএল কানেকশন কোড ব্যবহার করে যা এইচটিটিপি জিইটি, পোষ্ট ইত্যাদি করার সহজ পদ্ধতিতে কোডটি আবদ্ধ করে দেয় এবং গ্রন্থাগারটি তখন জেআর হিসাবে সংকলন ও প্যাকেজ করা যায় and জাভা কোডে আমদানিকৃত / ব্যবহৃত বা উত্স শ্রেণীর ফাইলটি জাভা প্রকল্পে অন্তর্ভুক্ত করা যেতে পারে যদি বাহ্যিক JARs পছন্দসই না হয়। এটি অ্যাপাচি ইত্যাদির মতো অন্যান্য লাইব্রেরিতে করা যেতে পারে তবে ইউআরএল কানেকশন ব্যবহার করে একটি সাধারণ 1 ফাইল শ্রেণির লাইব্রেরির তুলনায় অনেক বেশি ব্যথা হয়।
ডেভিড

র্যাপিডভ্যালুওলিউশনস / টেক_ব্লগ / H এইচটিপিএলসিএলএইচটিপিএল সংযোগের পক্ষে
রবীন্দ্র বাবু

24

আমি আপনাকে কেভিনসউইকি / এইচটিপি-রিকোয়েস্টের কোডটি একবার দেখে নেওয়ার পরামর্শ দিচ্ছি , মূলত এর শীর্ষে একটি র‌্যাপার HttpUrlConnectionআপনাকে এখনই অনুরোধগুলি করতে চাইলে বা উত্সগুলিতে একবার নজর দিতে পারেন (যদি আপনি এখনই অনুরোধগুলি করতে চান তবে এটি একটি অনেক সহজ এপিআই সরবরাহ করে) সংযোগগুলি কীভাবে পরিচালনা করা হয় তা একবার দেখার জন্য এটি খুব বেশি বড় নয়)।

উদাহরণ: GETসামগ্রীর ধরণ application/jsonএবং কিছু প্রশ্নের প্যারামিটার সহ একটি অনুরোধ করুন :

// GET http://google.com?q=baseball%20gloves&size=100
String response = HttpRequest.get("http://google.com", true, "q", "baseball gloves", "size", 100)
        .accept("application/json")
        .body();
System.out.println("Response was: " + response);

24

এইচটিটিপিএল ইউআরএল হিটগুলি সহ আপনি যেতে পারেন এমন দুটি বিকল্প রয়েছে: জিইটি / পোস্ট

অনুরোধ পান: -

HttpURLConnection.setFollowRedirects(true); // defaults to true

String url = "https://name_of_the_url";
URL request_url = new URL(url);
HttpURLConnection http_conn = (HttpURLConnection)request_url.openConnection();
http_conn.setConnectTimeout(100000);
http_conn.setReadTimeout(100000);
http_conn.setInstanceFollowRedirects(true);
System.out.println(String.valueOf(http_conn.getResponseCode()));

পোস্ট অনুরোধ: -

HttpURLConnection.setFollowRedirects(true); // defaults to true

String url = "https://name_of_the_url"
URL request_url = new URL(url);
HttpURLConnection http_conn = (HttpURLConnection)request_url.openConnection();
http_conn.setConnectTimeout(100000);
http_conn.setReadTimeout(100000);
http_conn.setInstanceFollowRedirects(true);
http_conn.setDoOutput(true);
PrintWriter out = new PrintWriter(http_conn.getOutputStream());
if (urlparameter != null) {
   out.println(urlparameter);
}
out.close();
out = null;
System.out.println(String.valueOf(http_conn.getResponseCode()));

3
আপনি কীভাবে আসল জেএসওএন প্রতিক্রিয়া দেখতে পারবেন?
সোর

21

আমি এই প্রতিক্রিয়া দ্বারা খুব অনুপ্রাণিত হয়েছিল।

আমি প্রায়শই এমন প্রকল্পগুলিতে থাকি যেখানে আমাকে কিছু এইচটিটিপি করা দরকার এবং আমি তৃতীয় পক্ষের অনেক বেশি নির্ভরশীলতা আনতে চাই না (যা অন্যকে নিয়ে আসে এবং ইত্যাদি))

আমি এই কথোপকথনের কয়েকটিটির উপর ভিত্তি করে আমার নিজস্ব ইউটিলিটিগুলি লিখতে শুরু করেছি (যেখানে হয়নি সেখানে):

package org.boon.utils;


import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.util.Map;

import static org.boon.utils.IO.read;

public class HTTP {

তারপরে কেবল একটি গুচ্ছ বা স্থির পদ্ধতি রয়েছে।

public static String get(
        final String url) {

    Exceptions.tryIt(() -> {
        URLConnection connection;
        connection = doGet(url, null, null, null);
        return extractResponseString(connection);
    });
    return null;
}

public static String getWithHeaders(
        final String url,
        final Map<String, ? extends Object> headers) {
    URLConnection connection;
    try {
        connection = doGet(url, headers, null, null);
        return extractResponseString(connection);
    } catch (Exception ex) {
        Exceptions.handle(ex);
        return null;
    }
}

public static String getWithContentType(
        final String url,
        final Map<String, ? extends Object> headers,
        String contentType) {
    URLConnection connection;
    try {
        connection = doGet(url, headers, contentType, null);
        return extractResponseString(connection);
    } catch (Exception ex) {
        Exceptions.handle(ex);
        return null;
    }
}
public static String getWithCharSet(
        final String url,
        final Map<String, ? extends Object> headers,
        String contentType,
        String charSet) {
    URLConnection connection;
    try {
        connection = doGet(url, headers, contentType, charSet);
        return extractResponseString(connection);
    } catch (Exception ex) {
        Exceptions.handle(ex);
        return null;
    }
}

তারপরে পোস্ট করুন ...

public static String postBody(
        final String url,
        final String body) {
    URLConnection connection;
    try {
        connection = doPost(url, null, "text/plain", null, body);
        return extractResponseString(connection);
    } catch (Exception ex) {
        Exceptions.handle(ex);
        return null;
    }
}

public static String postBodyWithHeaders(
        final String url,
        final Map<String, ? extends Object> headers,
        final String body) {
    URLConnection connection;
    try {
        connection = doPost(url, headers, "text/plain", null, body);
        return extractResponseString(connection);
    } catch (Exception ex) {
        Exceptions.handle(ex);
        return null;
    }
}



public static String postBodyWithContentType(
        final String url,
        final Map<String, ? extends Object> headers,
        final String contentType,
        final String body) {

    URLConnection connection;
    try {
        connection = doPost(url, headers, contentType, null, body);


        return extractResponseString(connection);


    } catch (Exception ex) {
        Exceptions.handle(ex);
        return null;
    }


}


public static String postBodyWithCharset(
        final String url,
        final Map<String, ? extends Object> headers,
        final String contentType,
        final String charSet,
        final String body) {

    URLConnection connection;
    try {
        connection = doPost(url, headers, contentType, charSet, body);


        return extractResponseString(connection);


    } catch (Exception ex) {
        Exceptions.handle(ex);
        return null;
    }


}

private static URLConnection doPost(String url, Map<String, ? extends Object> headers,
                                    String contentType, String charset, String body
                                    ) throws IOException {
    URLConnection connection;/* Handle output. */
    connection = new URL(url).openConnection();
    connection.setDoOutput(true);
    manageContentTypeHeaders(contentType, charset, connection);

    manageHeaders(headers, connection);


    IO.write(connection.getOutputStream(), body, IO.CHARSET);
    return connection;
}

private static void manageHeaders(Map<String, ? extends Object> headers, URLConnection connection) {
    if (headers != null) {
        for (Map.Entry<String, ? extends Object> entry : headers.entrySet()) {
            connection.setRequestProperty(entry.getKey(), entry.getValue().toString());
        }
    }
}

private static void manageContentTypeHeaders(String contentType, String charset, URLConnection connection) {
    connection.setRequestProperty("Accept-Charset", charset == null ? IO.CHARSET : charset);
    if (contentType!=null && !contentType.isEmpty()) {
        connection.setRequestProperty("Content-Type", contentType);
    }
}

private static URLConnection doGet(String url, Map<String, ? extends Object> headers,
                                    String contentType, String charset) throws IOException {
    URLConnection connection;/* Handle output. */
    connection = new URL(url).openConnection();
    manageContentTypeHeaders(contentType, charset, connection);

    manageHeaders(headers, connection);

    return connection;
}

private static String extractResponseString(URLConnection connection) throws IOException {
/* Handle input. */
    HttpURLConnection http = (HttpURLConnection)connection;
    int status = http.getResponseCode();
    String charset = getCharset(connection.getHeaderField("Content-Type"));

    if (status==200) {
        return readResponseBody(http, charset);
    } else {
        return readErrorResponseBody(http, status, charset);
    }
}

private static String readErrorResponseBody(HttpURLConnection http, int status, String charset) {
    InputStream errorStream = http.getErrorStream();
    if ( errorStream!=null ) {
        String error = charset== null ? read( errorStream ) :
            read( errorStream, charset );
        throw new RuntimeException("STATUS CODE =" + status + "\n\n" + error);
    } else {
        throw new RuntimeException("STATUS CODE =" + status);
    }
}

private static String readResponseBody(HttpURLConnection http, String charset) throws IOException {
    if (charset != null) {
        return read(http.getInputStream(), charset);
    } else {
        return read(http.getInputStream());
    }
}

private static String getCharset(String contentType) {
    if (contentType==null)  {
        return null;
    }
    String charset = null;
    for (String param : contentType.replace(" ", "").split(";")) {
        if (param.startsWith("charset=")) {
            charset = param.split("=", 2)[1];
            break;
        }
    }
    charset = charset == null ?  IO.CHARSET : charset;

    return charset;
}

হ্যাঁ, আপনি ধারণা পেতে পারেন....

টেস্টগুলি এখানে:

static class MyHandler implements HttpHandler {
    public void handle(HttpExchange t) throws IOException {

        InputStream requestBody = t.getRequestBody();
        String body = IO.read(requestBody);
        Headers requestHeaders = t.getRequestHeaders();
        body = body + "\n" + copy(requestHeaders).toString();
        t.sendResponseHeaders(200, body.length());
        OutputStream os = t.getResponseBody();
        os.write(body.getBytes());
        os.close();
    }
}


@Test
public void testHappy() throws Exception {

    HttpServer server = HttpServer.create(new InetSocketAddress(9212), 0);
    server.createContext("/test", new MyHandler());
    server.setExecutor(null); // creates a default executor
    server.start();

    Thread.sleep(10);


    Map<String,String> headers = map("foo", "bar", "fun", "sun");

    String response = HTTP.postBodyWithContentType("http://localhost:9212/test", headers, "text/plain", "hi mom");

    System.out.println(response);

    assertTrue(response.contains("hi mom"));
    assertTrue(response.contains("Fun=[sun], Foo=[bar]"));


    response = HTTP.postBodyWithCharset("http://localhost:9212/test", headers, "text/plain", "UTF-8", "hi mom");

    System.out.println(response);

    assertTrue(response.contains("hi mom"));
    assertTrue(response.contains("Fun=[sun], Foo=[bar]"));

    response = HTTP.postBodyWithHeaders("http://localhost:9212/test", headers, "hi mom");

    System.out.println(response);

    assertTrue(response.contains("hi mom"));
    assertTrue(response.contains("Fun=[sun], Foo=[bar]"));


    response = HTTP.get("http://localhost:9212/test");

    System.out.println(response);


    response = HTTP.getWithHeaders("http://localhost:9212/test", headers);

    System.out.println(response);

    assertTrue(response.contains("Fun=[sun], Foo=[bar]"));



    response = HTTP.getWithContentType("http://localhost:9212/test", headers, "text/plain");

    System.out.println(response);

    assertTrue(response.contains("Fun=[sun], Foo=[bar]"));



    response = HTTP.getWithCharSet("http://localhost:9212/test", headers, "text/plain", "UTF-8");

    System.out.println(response);

    assertTrue(response.contains("Fun=[sun], Foo=[bar]"));

    Thread.sleep(10);

    server.stop(0);


}

@Test
public void testPostBody() throws Exception {

    HttpServer server = HttpServer.create(new InetSocketAddress(9220), 0);
    server.createContext("/test", new MyHandler());
    server.setExecutor(null); // creates a default executor
    server.start();

    Thread.sleep(10);


    Map<String,String> headers = map("foo", "bar", "fun", "sun");

    String response = HTTP.postBody("http://localhost:9220/test", "hi mom");

    assertTrue(response.contains("hi mom"));


    Thread.sleep(10);

    server.stop(0);


}

@Test(expected = RuntimeException.class)
public void testSad() throws Exception {

    HttpServer server = HttpServer.create(new InetSocketAddress(9213), 0);
    server.createContext("/test", new MyHandler());
    server.setExecutor(null); // creates a default executor
    server.start();

    Thread.sleep(10);


    Map<String,String> headers = map("foo", "bar", "fun", "sun");

    String response = HTTP.postBodyWithContentType("http://localhost:9213/foo", headers, "text/plain", "hi mom");

    System.out.println(response);

    assertTrue(response.contains("hi mom"));
    assertTrue(response.contains("Fun=[sun], Foo=[bar]"));

    Thread.sleep(10);

    server.stop(0);


}

আপনি এখানে বাকীটি খুঁজে পেতে পারেন:

https://github.com/RichardHightower/boon

আমার লক্ষ্য হ'ল সাধারণ জিনিসগুলি যেগুলি আপনি আরও কিছুটা আরও সহজ উপায়ে করতে চান তা সরবরাহ করা ...


2
এটা যে বিজোড় doPost পদ্ধতিতে একটি charsetপ্যারাম রয়েছে, যা অনুরোধ শিরোনাম সেট করতে ব্যবহৃত হয়, তবে তারপরে কিছু হার্ড-কোডেড চারসেট দিয়ে ডেটা লেখা হয় IO.CHARSET। একটি বাগ?
ভিট খুডেনকো

21

হালনাগাদ

নতুন এইচটিটিপি ক্লায়েন্টটি জাভা 9 সহ প্রেরণ করা হয়েছে তবে ইনকিউবেটর মডিউলের অংশ হিসাবে jdk.incubator.httpclient। ইনকিউবেটর মডিউলগুলি ভবিষ্যত প্রকাশে চূড়ান্তকরণ বা অপসারণের দিকে অগ্রসর হওয়ার সময় বিকাশকারীদের হাতে অ-চূড়ান্ত এপিআইগুলি রাখার একটি মাধ্যম।

জাভা 9-তে, আপনি GETঅনুরোধ পাঠাতে পারেন:

// GET
HttpResponse response = HttpRequest
    .create(new URI("http://www.stackoverflow.com"))
    .headers("Foo", "foovalue", "Bar", "barvalue")
    .GET()
    .response();

তারপরে আপনি ফিরে আসা লোকদের পরীক্ষা করতে পারবেন HttpResponse:

int statusCode = response.statusCode();
String responseBody = response.body(HttpResponse.asString());

যেহেতু এই নতুন এইচটিটিপি ক্লায়েন্টটি রয়েছে java.httpclient jdk.incubator.httpclient মডিউল, আপনি আপনার মধ্যে এই নির্ভরতা ঘোষণা করা উচিত module-info.java ফাইলের :

module com.foo.bar {
    requires jdk.incubator.httpclient;
}

1
আরও আপডেট: মডিউলটি ইনকিউবেশন স্থিতির বাইরে। এটা তোলে এখন java.net.http , jdk.incubator.httpclient না।
ভিজিআর

17

প্রথমদিকে আমি এর দ্বারা বিভ্রান্ত হয়েছিলাম অনুগ্রহ নিবন্ধটিHttpClient

পরে আমি বুঝতে পেরেছি যে HttpURLConnection এই নিবন্ধ থেকে থাকতে চলেছে

গুগল ব্লগ অনুসারে :

অ্যাপাচি এইচটিটিপি ক্লায়েন্টের ইক্লেয়ার এবং ফ্রয়েওতে কম বাগ রয়েছে। এটি এই রিলিজের জন্য সেরা পছন্দ। জিঞ্জারব্রেডের জন্য, এইচটিটিপিআরএল সংযোগটি সেরা পছন্দ। এর সাধারণ এপিআই এবং ছোট আকার এটিকে অ্যান্ড্রয়েডের জন্য দুর্দান্ত ফিট করে।

স্বচ্ছ সংকোচন এবং প্রতিক্রিয়া ক্যাচিং নেটওয়ার্কের ব্যবহার হ্রাস করে, গতি উন্নত করে এবং ব্যাটারি সংরক্ষণ করে। নতুন অ্যাপ্লিকেশনগুলির HTTPURL সংযোগ ব্যবহার করা উচিত; এটিই যেখানে আমরা আমাদের শক্তিটি এগিয়ে যেতে ব্যয় করব।

এই নিবন্ধটি পড়ার পরে এবং প্রবাহের প্রশ্নগুলিতে কিছু অন্যান্য স্ট্যাক পড়ার পরে আমি নিশ্চিত হয়েছিHttpURLConnection দীর্ঘকাল স্থায়ী হতে চলেছে।

কিছু এসই প্রশ্নের পক্ষে HttpURLConnections:

অ্যান্ড্রয়েডে, urlEncodedFormEntity ব্যবহার না করে URL এনকোডড ফর্ম ডেটা দিয়ে একটি পোষ্ট অনুরোধ করুন

এইচটিপিপস্ট জাভা প্রকল্পে কাজ করে, অ্যান্ড্রয়েডে নয়


15

এখানে OkHttp রয়েছে , এটি একটি HTTP ক্লায়েন্ট যা ডিফল্টরূপে দক্ষ:

  • এইচটিটিপি / ২ সমর্থন একই হোস্টের সমস্ত অনুরোধকে সকেট ভাগ করে নেওয়ার অনুমতি দেয়।
  • সংযোগ পুলিং অনুরোধের বিলম্বকে হ্রাস করে (যদি HTTP / 2 উপলব্ধ না হয়)।
  • স্বচ্ছ জিজেআইপি ডাউনলোডের আকার সঙ্কুচিত করে।
  • প্রতিক্রিয়া ক্যাশে পুনরাবৃত্তির অনুরোধগুলির জন্য পুরোপুরি নেটওয়ার্ককে এড়িয়ে চলে।

প্রথমে এর উদাহরণ তৈরি করুন OkHttpClient:

OkHttpClient client = new OkHttpClient();

তারপরে, আপনার GETঅনুরোধ প্রস্তুত :

Request request = new Request.Builder()
      .url(url)
      .build();

অবশেষে, OkHttpClientপ্রস্তুত পাঠাতে ব্যবহার করুন Request:

Response response = client.newCall(request).execute();

আরও তথ্যের জন্য, আপনি OkHttp এর ডকুমেন্টেশনগুলির সাথে পরামর্শ করতে পারেন


14

এছাড়াও আপনি ব্যবহার করতে পারেন JdkRequestথেকে jcabi-HTTP (আমি একজন বিকাশকারী আছি), যা, শোভাকর HttpURLConnection HTTP অনুরোধ অগ্নিসংযোগ এবং প্রতিক্রিয়া পার্স উদাহরণস্বরূপ, আপনার জন্য সব কাজ করে:

String html = new JdkRequest("http://www.google.com").fetch().body();

আরও তথ্যের জন্য এই ব্লগ পোস্টটি দেখুন: http://www.yegor256.com/2014/04/11/jcabi-http-intro.html


1
আপনি কীভাবে কুকিজ পরিচালনা করবেন?
দেজেল

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.