Android+Tomcat通过http获取本机服务器资源

写在前面:本博客为本人原创,严禁任何形式的转载!本博客只允许放在博客园(.cnblogs.com),如果您在其他网站看到这篇博文,请通过下面这个唯一的合法链接转到原文!

本博客全网唯一合法URL:http://www.cnblogs.com/acm-icpcer/p/8521625.html

 

 

   最近尝试了一下使用tomcat把自己的笔记本作为项目的服务器。

  tomcat下载:https://tomcat.apache.org/download-90.cgi

  当然啦,你可以选择点击zip进行免安装下载(即下载了zip包之后解压即可),或者点击32-bit/64-bit windows service installer进行.exe安装包的下载。

  下载后我一般喜欢在我选择的下载路径里面的bin文件夹下双击Tomcat9w.exe启动。

 

  启动之后的界面:

  点击start后,tomcat就启动了,它所产生的进程就一直处于监听有没有访问请求的状态。

  tomcat服务器的细节配置方法比较原始,是在安装路径下的conf文件夹下面的server.xml文件里进行代码的改写来自定义配置,在此先不详述。

  安装好后我们可以用一个小的web项目来测试服务器是否安装成功:

  我使用的项目是我寒假为我的网页游戏弹弹堂的公会做的官方网站,因为纯粹是前端项目,所以正好可以用来测试。主要方法是:将网站的代码包整个的复制到tomcat下的webapps文件夹(这样就算是在服务器端部署成功了)。

  然后测试访问的有效性:先在命令行模式下通过ipconfig命令查看计算机的ipv4地址:

  可以看到我的地址是172.16.124.241,然后在浏览器上输入172.16.124.241:8080/shengyu_shenhua来访问,":8080"是tomcat服务器默认的访问端口,端口号可以在前面提到的server.xml文件里进行修改,"/shengyu_shenhua"是放在服务端webapps文件夹里的网站项目的名字。当然了,使用localhost:8080/shengyu_shenhua来访问也是可以的,但我更习惯使用IP地址访问。

  可以访问网页了就说明现在tomcat服务器安装好了。但是此时的tomcat服务器只能给连接在相同路由器的终端访问,因为通常来说,isp给你通的网都不会有固定的ip,所以过一段时间你的电脑ip就会改变,除非isp给你牵了专线。所以通过IP的访问是不稳定的,在没有固定服务器或者云服务的情况下,tomcat还是适合在局域网内使用。

下面讲讲怎么让Android通过http访问局域网内tomcat服务器上的资源:

  一般来说,使用android开发进行http链接,会用url来访问资源,但是网络连接线程不能放在主线程,因为当网络连接不成功时会抛出主线程异常,所以一般会另开一个线程来保持网络连接:

  

  MainActivity.java代码:

package com.example.administrator.tryserver;

import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ImageView;

import org.json.JSONException;
import org.json.JSONObject;

import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;

public class MainActivity extends Activity {

    private ImageView ivImg;
    private Button btnDownload;
    private Bitmap img;
    private ImageHandler imgHandler = new ImageHandler();
    //测试Url
    private String url = "http://172.16.124.241:8080/img/1.jpg";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ivImg = (ImageView) findViewById(R.id.imageView1);
        btnDownload = (Button) findViewById(R.id.button1);
        //点击按钮开始下载
        btnDownload.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                downloadImg();
            }
        });
    }

    /**
     * 异步从服务器加载图片数据
     */
    private void downloadImg(){
        new Thread(new Runnable() {
            @Override
            public void run() {
                Bitmap img =  getImg();
                Message msg = imgHandler.obtainMessage();
                msg.what = 0;
                msg.obj = img;
                imgHandler.sendMessage(msg);
            }
        }).start();
    }

    /**
     * 异步线程请求到的图片数据,利用Handler,在主线程中显示
     */
    class ImageHandler extends Handler{
        @Override
        public void handleMessage(Message msg) {

            switch (msg.what) {
                case 0:
                    img = (Bitmap)msg.obj;
                    if(img != null){
                        ivImg.setImageBitmap(img);
                    }
                    break;

                default:
                    break;
            }
        }
    }

    /**
     * 从服务器读取图片流数据,并转换为Bitmap格式
     * @return Bitmap
     */
    private Bitmap getImg(){
        Bitmap img = null;

        try {
            URL imgUrl = new URL(url);
            HttpURLConnection conn = (HttpURLConnection) imgUrl.openConnection();

            conn.setRequestMethod("POST");
            conn.setConnectTimeout(1000 * 6);
            conn.setDoInput(true);
            conn.setDoOutput(true);
            conn.setUseCaches(false);

            conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
            conn.setRequestProperty("Connection", "Keep-Alive");
            conn.setRequestProperty("Charset", "UTF-8");
            conn.connect();

            //输出流写参数
            DataOutputStream dos = new DataOutputStream(conn.getOutputStream());
            String param = getParam();
            dos.writeBytes(param);
            dos.flush();
            dos.close();

            int resultCode = conn.getResponseCode();

            if(HttpURLConnection.HTTP_OK == resultCode){
                InputStream is = conn.getInputStream();
                img = BitmapFactory.decodeStream(is);
                is.close();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }

        return img;
    }

    /**
     * 测试参数
     * @return
     */
    private String getParam(){
        JSONObject jsObj = new JSONObject();
        try {
            jsObj.put("picFormat", "jpg");
            jsObj.put("testParam", "9527");
        } catch (JSONException e) {
            e.printStackTrace();
        }

        return jsObj.toString();
    }
}

  界面文件activity_main.xml文件代码:

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

    <EditText
        android:id="@+id/editText1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:ems="10" >

        <requestFocus />
    </EditText>

    <Button
        android:id="@+id/button1"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="点击获取URL资源" />

    <ImageView
        android:id="@+id/imageView1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"/>

</LinearLayout>

  当然了,不要忘了在AndroidManifest.xml文件里面加上打开网络权限的语句:

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

  AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.administrator.tryserver">
    <uses-permission android:name="android.permission.INTERNET"/>

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

  这个项目主要是在局域网环境下,当你点击button,就可以在android界面显示url里面指定服务器内的图片资源(在此是:http://172.16.124.241:8080/img/1.jpg)。如果希望在互联网访问Tomcat服务器资源,只需要设置路由器的路由映射,将路由器的IP地址指定映射到你的电脑的特定端口(在此是8080)即可,设置好后,就是使用http协议在互联网访问你的Tomcat服务器资源了。

  只要保持在同一局域网下,不论是android真机还是虚拟机都是可以的。只不过在用虚拟机访问的时候不能用"http://localhost:8080/img/1.jpg"这个url,因为这样的话,localhost指代虚拟机本机而不是运行虚拟机的主机,故使用"http://10.0.2.2:8080/img/1.jpg"来访问主机资源。在虚拟机下,"http://10.0.2.2:8080/img/1.jpg"以及"http://172.16.124.241:8080/img/1.jpg"这两个url都是可以的,唯独不能使用"http://localhost:8080/img/1.jpg"这个url。当然,使用Android真机调试的时候还会遇到手机连接到了主机usb接口,但是android studio识别不到的问题,一般是没有打开手机的开发者模式或者手机没有能正确的安装设备驱动程序(此时应该上手机的官方网站下载驱动)。

注:因为今天是女生节,所以测试用的图片资源是一个日系卡通萌妹子。原画作者:德田有希,日本漫画家&一个可爱的男孩子。

TZ@华中农业大学信息学院

2018/3/7

原文地址:https://www.cnblogs.com/acm-icpcer/p/8521625.html