android通过HttpURLConnection/HttpClient(post)方式与servlet(tomcat)进行交互(servlet实现的功能是计算两个数字的积)
我的电脑里已经配置好了Tomcat.
Tomcat的安装和环境配置这里不再做演示。
今天我们做的实验内容是:
这里先写一个通过以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
图1-2
这是模拟器的显示结果:
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 "获取失败"; } } }
以上就是全部内容啦!我的第一篇博客啦啦啦啦啦。。。