android通过HttpURLConnection/HttpClient(post)方式与servlet(tomcat)进行交互(servlet实现的功能是计算两个数字的积)

我的电脑里已经配置好了Tomcat.

Tomcat的安装和环境配置这里不再做演示。

今天我们做的实验内容是:

android通过HttpURLConnection/HttpClient(post)方式与servlet(tomcat)进行交互(servlet实现的功能是计算两个数字的积)

这里先写一个通过以HttpURLConnection的post方式进行通信,直接贴代码,代码里的注解写得很详细,对了我用的android studio和eclipse

eclipse端的代码往下看截图1-2,很简单,这里不再过多赘述

这里先交代一下HttpURLConnection实现流程:

1、创建HttpURLConnection实例

2、用openConnection创建HttpURLConnection实例

3、建立连接,可以通过connect()方法,也可以直接通过getOutputStream()方法建立连接

4、通过HttpURLConnection写数据与发送数据

5、通过getInputStream()方法,将HTTP请求发送到服务器,并取得返回数据

6、在AndroidManifest.xml文件中添加权限

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

android studio 端代码:

public class MainActivity extends AppCompatActivity {
    TextView t1;
    private Handler handler=new Handler(){
        //这里接受sendMessage()发来的数据msg1
        public void handleMessage(android.os.Message msg){
            Bundle bundle = new Bundle();
            bundle = msg.getData();
            String p = bundle.getString("result");
            if(p != null){
                t1.setText(p);
            }
        };
    };
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        final EditText e1=(EditText) findViewById(R.id.editText1);
        final EditText e2=(EditText) findViewById(R.id.editText2);
        Button b1=(Button) findViewById(R.id.button);
        Button b2=(Button) findViewById(R.id.button2);
        t1=(TextView) findViewById(R.id.textView);
        //设置按钮“计算结果”的点击事件
        b1.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                //定义路径LOGIN_URL,模拟器进行测试时10.0.2.2表示本机的IP地址,8080代表端口号,androidexphttpclient是我在eclipse里创建的模拟服务器的包名
                // calculateservlet是servlet的类名,见下面的图1-1和1-2
                final String URL = "http://10.0.2.2:8080/androidexphttpclient/calculateservlet";
                if (e1.getText().toString().isEmpty()||e2.getText().toString().isEmpty()) {
                    Toast.makeText(MainActivity.this, "输入不能为空", Toast.LENGTH_SHORT).show();
                }
                else{
                    //开启访问服务器的线程,android4.0之后不能在UI线程访问网络,子线程也不能更新UI界面
                    new Thread(new Runnable() {
                        @Override
                        public void run() {
                            String msg = "";
                            try {
                                //生成一个URL实例,指向我们刚才设定的地址URL
                                java.net.URL url = new URL(URL);
                                //openConnection()方法只是创建了一个HttpURLConnection实例,并不进行真正的连接操作,在连接之前可以设置一些属性
                                HttpURLConnection conn = (HttpURLConnection) url.openConnection();
                                //设置请求方式为post
                                conn.setRequestMethod("POST");
                                //设置超时信息
                                conn.setReadTimeout(5000);
                                conn.setConnectTimeout(5000);
                                //设置输入流,允许输入(关于java流的概念我也是前天又复习上个学期的Java书看才算有一点理解了,之前一直很蒙圈
                                // 死记硬背什么读进来,写出去,这个概念确实不好懂,反复去琢磨吧)
                                conn.setDoInput(true);
                                //设置输出流,允许输出
                                conn.setDoOutput(true);
                                //设置POST请求方式不能够使用缓存
                                conn.setUseCaches(false);
                                //定义我们要传给servlet的参数,这里进行了编码,去掉编码就是:data="p1=password&p2=username"键值对的形式
                                String data = "p1=" + URLEncoder.encode(e1.getText().toString(), "UTF-8") +
                                        "&p2=" + URLEncoder.encode(e2.getText().toString(), "UTF-8");
                                //获取输出流,其实在这之前还应该有一个操作:conn.connect();意思为建立HttpURLConnection连接,只不过getOutputStream()方法
                                // 会隐含进行连接,所以不调用connect()也可以建立连接
                                OutputStream out = conn.getOutputStream();
                                //把data里的数据以字节的形式写入out流中(相当于把数据放到了从这里连接到servlet的管子里,数据就是水)
                                out.write(data.getBytes());
                                //刷新,将数据缓冲区中的数据全部输出,并清空缓冲区
                                out.flush();
                                //关闭输出流并释放与流相关的资源
                                out.close();
                                //这里是将conn.getInputStream中的数据包装在字符流的缓冲流reader中,这里是简写,看不懂的话就复习一下java的I/O吧
                                //这里值得一说的是:无论是post还是get,http请求实际上直到HttpURLConnection的getInputStream()这个函数
                                //里面才正式发出去,同时getInputStream返回的值就是servlet返回的数据,也就是我们这里求的积!!!
                                BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream()));
                                String line = null;
                                if ((line = reader.readLine()) != null) {
                                    msg = line;
                                }
                                Bundle bundle = new Bundle();
                                bundle.putString("result",msg);
                                Message msg1 = new Message();
                                msg1.setData(bundle);
                                //调用Handler的sendMessage()方法,这个消息将存在UI线程的MessageQueue中,通过Looper对象(在主线程中
                                // 创建Handler对象时,系统已经创建好了Looper对象,所以这里不用手动创建Looper对象,如果是在子线程中
                                // 的Handler对象,需要调用Looperloop()方法开启消息循环)取出MessageQueue中的消息,最后传到Handler的handlerMessage()
                                //方法中
                                handler.sendMessage(msg1);
                                conn.disconnect();
                            } catch (IOException e) {
                                e.printStackTrace();
                            }

                        }
                    }).start();
                }

            }
        });
        //点击清空按钮清除text里的信息
        b2.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                t1.setText("");
            }
        });
    }
}


图1-1

android通过HttpURLConnection/HttpClient(post)方式与servlet(tomcat)进行交互(servlet实现的功能是计算两个数字的积)


图1-2

android通过HttpURLConnection/HttpClient(post)方式与servlet(tomcat)进行交互(servlet实现的功能是计算两个数字的积)

这是模拟器的显示结果:

android通过HttpURLConnection/HttpClient(post)方式与servlet(tomcat)进行交互(servlet实现的功能是计算两个数字的积)


HttpClient(post)方式流程:

1、创建HttpPost对象,将要请求的URL通过构造方法传入HttpPost对象

2、使用DefaultHttpClient类的execute()方法发送HTTP POST请求,并返回HttpResponse对象

3、通过HttpResponse接口的getEntity方法返回响应信息,并进行相应处理

4、在AndroidManifest.xml文件中添加权限

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


接下来贴HttpClient的post方式连接的代码:

public class MainActivity extends AppCompatActivity {
    TextView t1;
//    private Handler handler=new Handler(){
//        //这里接受sendMessage()发来的数据msg1
//        public void handleMessage(android.os.Message msg){
//            Bundle bundle = new Bundle();
//            bundle = msg.getData();
//            String p = bundle.getString("result");
//            if(p != null){
//                t1.setText(p);
//            }
//        };
//    };
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        final EditText e1=(EditText) findViewById(R.id.editText1);
        final EditText e2=(EditText) findViewById(R.id.editText2);
        Button b1=(Button) findViewById(R.id.button);
        Button b2=(Button) findViewById(R.id.button2);
        t1=(TextView) findViewById(R.id.textView);
        //设置按钮“计算结果”的点击事件
        b1.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                //定义路径LOGIN_URL,模拟器进行测试时10.0.2.2表示本机的IP地址,8080代表端口号,androidexphttpclient是我在eclipse里创建的模拟服务器的包名
                // calculateservlet是servlet的类名,见图1-1
                final String URL = "http://10.0.2.2:8080/androidexphttpclient/calculateservlet";
                if (e1.getText().toString().isEmpty()||e2.getText().toString().isEmpty()) {
                    Toast.makeText(MainActivity.this, "输入不能为空", Toast.LENGTH_SHORT).show();
                }
                new Thread(){
                    public void run(){
                        try {
                            //在API 23中,Google已经移除了移除了Apache HttpClient相关的类 。谷歌推荐使用HttpUrlConnection,
                            //如果要继续使用需要Apache HttpClient,需要在Eclipse下libs里添加org.apache.http.legacy.jar,
                            //Android studio里在相应的module下的build.gradle中加入即可。android { useLibrary 'org.apache.http.legacy'}
                            //下面8行就是对HttpClient的一个具体操作,涉及的东西挺多的
                            //获取HttpClient对象
                            HttpClient client = new DefaultHttpClient();
                            //post方式请求网络
                            HttpPost httpPost=new HttpPost(URL);
                            //指定要提交的数据实体,NameValuePair接口是一个简单的封闭的键值对,提供了BasicNameValuePair(String name,String value)
                            //方法指定要传入的参数的名称和内容
                            List<NameValuePair> parameters=new ArrayList<NameValuePair>();
                            parameters.add(new BasicNameValuePair("p1",e1.getText().toString()));
                            parameters.add(new BasicNameValuePair("p2",e2.getText().toString()));
                            httpPost.setEntity(new UrlEncodedFormEntity(parameters,"UTF-8"));
                            //请求服务器并获取服务器返回的信息
                            HttpResponse response=client.execute(httpPost);
                            //获取状态码
                            int code=response.getStatusLine().getStatusCode();
                            //访问成功
                            if(code==200){
                                InputStream is=response.getEntity().getContent();
                                //将输入流转换成字符串
                                final String text=StreamTools.readInputStream(is);
                                //这里和上面一样可以使用handler.sendMessage()将信息传送到消息队列里去
//                                Message msg=new Message();
//                                Bundle bundle=new Bundle();
//                                bundle.putString("result",text);
//                                msg.setData(bundle);
//                                handler.sendMessage(msg);
                                //这里我们除了可以使用Handler来更新主线程UI,也可以用runOnUiThread()方法来更新,顾名思义,就是跑在Ui上的线程。这个更简单粗暴!!
                                runOnUiThread(new Runnable() {
                                    @Override
                                    public void run() {
                                        t1.setText(text);
                                    }
                                });
                            }
                        }catch (Exception e){
                            e.printStackTrace();
                        }
                    }
                }.start();
            }
        });
        //点击清空按钮清除text里的信息
        b2.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                t1.setText("");
            }
        });
    }
}
//这里定义了一个StreamTools类,用来将输入流(也就是把servlet端到本程序的管道里的水(数据)的状态变为字符串)中的内容转化为字符串
class StreamTools{
    public static String readInputStream(InputStream is){
        try{
            ByteArrayOutputStream baos=new ByteArrayOutputStream();
            int len=0;
            byte[] buffer=new byte[1024];
            while((len=is.read(buffer)) != -1){
                baos.write(buffer,0,len);
            }
            is.close();
            baos.close();
            byte[] result=baos.toByteArray();
            String temp=new String(result);
            return temp;
        }catch (Exception e){
            e.printStackTrace();
            return  "获取失败";
        }
    }
}

以上就是全部内容啦!我的第一篇博客啦啦啦啦啦。。。