Android中的HTTP请求

本文详细介绍了Android中的两种网络请求方式:HttpURLConnection与HttpClient,并通过一个登录功能实例展示了这两种方式的具体应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

基本介绍


HTTP 协议可能是现在 Internet 上使用得最多、最重要的协议了,越来越多的 Java 应用程序需要直接通过 HTTP 协议来访问网络资源。在 JDK 的 java.net 包中已经提供了访问HTTP协议的基本功能:HttpURLConnection。
但是对于大部分应用程序来说,JDK 库本身提供的功能还不够丰富和灵活。 除此之外,在Android中,androidSDK中集成了Apache的HttpClient模块,用来提供高效的、最新的、功能丰富的支持 HTTP 协议工具包。


Android有哪些HTTP请求编程形式呢?

java原生的–HttpURLConnection
Apache提供的–HttpClient

他们有什么区别?

我们根据Volley框架的源码,发现它在HTTP请求的使用上是这样的,在Android 2.3及以上版本,使用的是HttpURLConnection,而在Android 2.2及以下版本,使用的是HttpClient。这两种方式都支持HTTPS协议、以流的形式进行上传和下载、配置超时时间、IPv6、以及连接池等功能。

DefaultHttpClient和AndroidHttpClient都是HttpClient具体的实现类,它们都拥有众多的API,而且实现比较稳定,bug数量也很少。但同时也由于HttpClient的API数量过多,使得我们很难在不破坏兼容性的情况下对它进行升级和扩展,所以目前Android团队在提升和优化HttpClient方面的工作态度并不积极。

HttpURLConnection是一种多用途、轻量极的HTTP客户端,使用它来进行HTTP操作可以适用于大多数的应用程序。虽然HttpURLConnection的API提供的比较简单,但是同时这也使得我们可以更加容易地去使用和扩展它。
不过在Android2.2版本之前,HttpURLConnection一直存在着一些令人厌烦的bug。比如说对一个可读的InputStream调用close()方法时,就有可能会导致连接池失效了。那么我们通常的解决办法就是直接禁用掉连接池的功能

在Android 2.2版本之前,HttpClient拥有较少的bug,因此使用它是最好的选择。

而在Android2.3版本及以后,HttpURLConnection则是最佳的选择。它的API简单,体积较小,因而非常适用于Android项目。压缩和缓存机制可以有效地减少网络访问的流量,在提升速度和省电方面也起到了较大的作用。对于新的应用程序应该更加偏向于使用HttpURLConnection,因为在以后的工作当中我们也会将更多的时间放在优化HttpURLConnection上面。

http请求形式有哪些呢?

网络请求方式可分为get请求,post两种请求方式
GET方式在进行数据请求时,会把数据附加到URL后面传递给服务器,比如常见的:http://XXX.XXX.XXX/XX.jsp ? id=1
POST方式则是将请求的数据放到HTTP请求头中,作为请求头的一部分传入服务器。
所以,在进行HTTP编程前,首先要明确究竟使用的哪种方式进行数据请求。



应用实例


下面我们开始用一个简单的登陆功能来对HttpUrlConnection和HttpClient的交互进行展示,Android端将用户名和密码发送给后台进行验证处理,然后后台针对传来数据解析然后返回给客户端一个登陆的结果。
首先我们需要一个通用的服务器的处理登陆的程序,我们以一个servlet来进行服务器端的处理

———————————————服务器部分————————————————-

- - Servlet登陆 - -

我们首先需要建立一个web工程,然后在工程中创建一个Servlet类:LoginServlet
然后在xml配置文件中配置这个servlet,在这个servlet中我们包含了两种处理形式来分别处理GET和POST

public class LoginServlet extends HttpServlet {

    private Map<String, String> map; // 模拟数据库的作用,其中放入用户名和密码

    public LoginServlet() {
        super();
    }

    @Override
    public void init() throws ServletException {
        super.init();
        map = new HashMap<String, String>();
        map.put("Johnson", "123");
        map.put("John", "321");
    }

    @Override
    public void destroy() {
        super.destroy();
    }

    @Override
    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        doPost(request, response);
    }

    @Override
    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        PrintWriter out = response.getWriter();
        String username = request.getParameter("name");
        String password = request.getParameter("password");
        boolean isExist = false;

        // 模拟查询数据库
        for (String name : map.keySet()) {
            System.out.println(name+1);
            if (name.equals(username)) {
                System.out.println(map.get(name)+2);
                if (password.equals(map.get(name))) {
                    System.out.println("对的");
                    isExist = true;
                }
            }
        }
        System.out.println(isExist);

        if (isExist == true) {// 用户名存在
            String jsonString = "{code : 1}";
            out.write(jsonString);
        } else {// 用户名或密码错误

            String jsonString = "{code : 0} ";
            out.write(jsonString);
        }

    }

}

———————————————客户端部分————————————————–

Android端首先创建一个工程,这个界面只有两个EditText和一个Button,分别用于输入用户名和密码,按钮用于提交请求 以下是界面xml代码

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center"
    android:orientation="vertical" >

    <EditText
        android:id="@+id/username"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="用户名"
        android:textSize="16sp" />

    <EditText
        android:id="@+id/password"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="20dp"
        android:hint="密码"
        android:textSize="16sp" />

    <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="20dp"
        android:onClick="login"
        android:text="登   陆" />

</LinearLayout>

界面效果


然后我们就是主要的功能部分代码,代码中有HttpUrlConnectionTool和HttoClientTool就是我们整合的两种不同请求方式的工具,在下面会有分别对应的相关网络工具类代码

- - **MainActivity界面** - -

public class MainActivity extends Activity {

    private EditText user;
    private EditText password;
    private String name;// 记录用户名
    private String passwd;// 记录密码
    private Map<String, String> mMap;

    String url = "http://localhost:8080/LoginServlet/login";// 服务器登陆地址

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        user = (EditText) findViewById(R.id.username);
        password = (EditText) findViewById(R.id.password);

    }

    // 点击登陆
    public void login(View view) {
        name = user.getText().toString();
        passwd = password.getText().toString();
        mMap = new HashMap<String, String>();
        mMap.put("name", name);
        mMap.put("password", passwd);
        new MyAsyncTask().execute(url);
    }

    class MyAsyncTask extends AsyncTask<String, Void, Integer> {

        @Override
        protected Integer doInBackground(String... params) {

            // 以下四个为http的四个请求方法
            int code = HttpClientTool.getMethod(params[0], mMap);
            // int code = HttpClientTool.postMethod(params[0], mMap);
            // int code = HttpUrlConnectionTool.doGet(params[0], mMap);
            // int code = HttpUrlConnectionTool.doPost(params[0], mMap);
            return code;
        }

        @Override
        protected void onPostExecute(Integer result) {
            if (result == 0) {
                Toast.makeText(MainActivity.this, "用户名或密码错误", Toast.LENGTH_LONG)
                        .show();
            } else if (result == 1) {
                Toast.makeText(MainActivity.this, "登陆成功 ", Toast.LENGTH_LONG)
                        .show();
            } else {

            }
            super.onPostExecute(result);
        }

    }
}

- - HttpClient方式 - -

这里我们用HttpClient方式进行网络交互,代码如下

public class HttpClientTool {

    /**
     * GET方式登陆
     * 
     * @param url
     * @param map
     * @return
     */
    public static int getMethod(String url, Map<String, String> map) {
        // code为1登陆成功 0登陆失败
        HttpClient httpClient = new DefaultHttpClient();
        int code = 0;
        StringBuilder builder = new StringBuilder(url + "?");

        for (String key : map.keySet()) {
            String value = map.get(key);
            builder.append(key + "=" + value);
            builder.append("&");
        }
        builder.deleteCharAt(builder.length() - 1);// 去掉最后一个&
        String mUrl = builder.toString();

        try {

            HttpGet httpGet = new HttpGet(mUrl);
            HttpResponse response = httpClient.execute(httpGet);

            int responseCode = response.getStatusLine().getStatusCode();
            if (responseCode == HttpStatus.SC_OK) {
                HttpEntity entity = response.getEntity();
                // 传回来的是一个json数据
                String jsonEntity = EntityUtils.toString(entity);
                Log.i("tag",jsonEntity+"---------");
                JSONObject jsonObject = new JSONObject(jsonEntity);
                code = jsonObject.getInt("code");
            }

        } catch (ClientProtocolException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (JSONException e) {
            e.printStackTrace();
        }
        return code;
    }

    /**
     * POST方式登陆
     * 
     * @param url
     * @param map
     * @return
     */
    public static int postMethod(String url, Map<String, String> map) {
        // code为1登陆成功 0登陆失败
        HttpClient httpClient = new DefaultHttpClient();
        int code = 0;
        List<NameValuePair> mList = new ArrayList<NameValuePair>();
        for (String key : map.keySet()) {
            String value = map.get(key);
            mList.add(new BasicNameValuePair(key, value));
        }

        try {
            // 使用HttpPost对象设置发送的URL路径
            HttpPost httpPost = new HttpPost(url);
            // 把请求参数变成请求体部分
            UrlEncodedFormEntity uee = new UrlEncodedFormEntity(mList, "utf-8");
            // 使用HttpPost对象设置发送的URL路径
            httpPost.setEntity(uee);
            HttpResponse response = httpClient.execute(httpPost);

            int resultCode = response.getStatusLine().getStatusCode();
            if (resultCode == HttpStatus.SC_OK) {
                HttpEntity entity = response.getEntity();
                // 传回来的是一个json数据
                String jsonEntity = EntityUtils.toString(entity);
                JSONObject jsonObject = new JSONObject(jsonEntity);
                code = jsonObject.getInt("code");
            }
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        } catch (ClientProtocolException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (JSONException e) {
            e.printStackTrace();
        }
        return code;
    }
}

- - HttpUrlConnection方式 - -

以下是HttpUrlConnection方式进行访问服务器,这样的方式更加灵活和便于自定义

public class HttpUrlConnectionTool {

    // get方式
    public static int doGet(String mUrl, Map<String, String> map) {

        int code = 0;
        StringBuilder builder = new StringBuilder(mUrl + "?");

        for (String key : map.keySet()) {
            String value = map.get(key);
            builder.append(key + "=" + value);
            builder.append("&");
        }
        builder.deleteCharAt(builder.length() - 1);// 去掉最后一个&
        String finalUrl = builder.toString();

        try {

            URL url = new URL(finalUrl);
            HttpURLConnection connection = (HttpURLConnection) url
                    .openConnection();
            // 设定请求的方法为"GET",默认是GET
            connection.setRequestMethod("GET");
            // 设置是否从httpUrlConnection读入,默认情况下是true;
            connection.setDoInput(true);
            // GET 请求可以使用缓存
            connection.setUseCaches(true);
            // 设定传送的内容类型是可序列化的java对象
            // (如果不设此项,在传送序列化对象时,当WEB服务默认的不是这种类型时可能抛java.io.EOFException)
            connection.setRequestProperty("Content-type",
                    "application/x-java-serialized-object");
            // 连接,从上述url.openConnection()至此的配置必须要在connect之前完成,
            connection.connect();
            BufferedReader br = new BufferedReader(new InputStreamReader(
                    connection.getInputStream(), "utf-8"));
            StringBuilder result = new StringBuilder(); // 接收返回的Json字符串
            String line;
            while ((line = br.readLine()) != null) {
                result.append(line);
            }
            JSONObject jsonObject = new JSONObject(result.toString());
            code = jsonObject.getInt("code");

        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (JSONException e) {
            e.printStackTrace();
        }

        return code;

    }

    // post方式
    public static int doPost(String mUrl, Map<String, String> map) {

        int code = 0;
        StringBuilder builder = new StringBuilder();

        for (String key : map.keySet()) {
            String value = map.get(key);
            builder.append(key + "=" + value);
            builder.append("&");
        }
        builder.deleteCharAt(builder.length() - 1);// 去掉最后一个&
        String params = builder.toString();

        try {

            URL url = new URL(mUrl);
            HttpURLConnection connection = (HttpURLConnection) url
                    .openConnection();
            connection.setConnectTimeout(5000);
            connection.setRequestMethod("POST");
            connection.setDoInput(true);
            // 设置是否向httpUrlConnection输出,因为这个是post请求,参数要放在http正文内需要设为true,
            // 默认情况下是false;
            connection.setDoOutput(true);
            // post方式不支持缓存
            connection.setUseCaches(false);
            BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(
                    connection.getOutputStream(), "utf-8"));
            bw.write(params);
            bw.flush();
            bw.close();
            // 调用此方法就不必再使用conn.connect()方法
            int responseCode = connection.getResponseCode();
            if (responseCode == HttpStatus.SC_OK) {
                BufferedReader br = new BufferedReader(new InputStreamReader(
                        connection.getInputStream(), "utf-8"));
                StringBuilder result = new StringBuilder();
                String line;
                while ((line = br.readLine()) != null) {
                    result.append(line);
                }
                JSONObject jsonObject = new JSONObject(result.toString());
                code = jsonObject.getInt("code");
            } else {
                Log.i("error", "访问失败");
            }

        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (JSONException e) {
            e.printStackTrace();
        }

        return code;

    }
}

以上就是Android中对网络访问的两种形式,最后别忘了在Android项目中的配置文件中加入

 <uses-permission android:name="android.permission.INTERNET"/>

这样就可以实现简单的登陆效果了

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值