首页 > 代码库 > 使用 Android 客户端向 Ruby on rails 构建的 Web Application 提交 HTTP GET 和 HTTP POST 请求

使用 Android 客户端向 Ruby on rails 构建的 Web Application 提交 HTTP GET 和 HTTP POST 请求

最近想弄个能访问 Internet 的 Android 应用,因为求快所以用了 Ruby on Rails 来提供 HTTP 资源。这方面的资料还是比较少的,所以把尝试的过程记录下来。

 

1 使用 Ruby on Rails 构建 Web Application

 

1.1 新建 Web Application

rails new Test 
cd Test

1.2 生成 product

rails generate scaffold product reference:string quantity:decimal
rake db:migrate

 启动服务

rails server

 打开http://localhost:3000/products

 应该可以看到以下信息(这个就是GET的结果啦,只不过现在还没有记录):

 在网页上添加一条记录,单击“New Product”,会转到“http://localhost:3000/products/new”,在里面填写信息后单击“Greate Product”(这样就提交了一个 POST):

也就是说,网页端的 GET 和 POST 都是可以执行的。

 

1.3 使用 Json 格式传输数据

先试试 GET Json 格式的数据

打开:http://localhost:3000/products/1.json

可以看到,使用 ruby on rails 是可以直接获得 Json 数据的,这是为什么呢?

为了弄清楚 Json 数据是怎么来的,先查看 routes

rake routes

显示出以下结果:

所以输入的 http://localhost:3000/products/1.json 对应的是 Controller 里面的 show,在代码里找到show(Test/app/controllers/products_controller.rb):

咦!什么情况?啥都不写就能直接支持 Json ?这也太牛逼了吧。

 

再试试 Post Json 格式的数据

前面已经知道,用网页可以提交一个 POST,先跟踪一下下这个 POST,用开发者工具查看网络知道页面提交的时候提交了一个 POST:

这个 POST 根据前面的 Routes 应该是给了 controller 里的 create。

所以是 @product = Product.new(product_params) 创建对象,@product.save 保存对象。。那么 product_params 怎么来的呢?

好吧,是这样来的。。。

 

嗯。。还是没有解决我想要的 Json 传输方法,后来还是搜索找大神。。。

在 Test/app/controllers/products_controller.rb 中添加以下代码,用于接受 Android App 提交的 Json 数据。

  def create_from_app
      data_json=JSON.parse request.body.read
      @product = Product.new(data_json)
      @product.save
  end

 

1.4 测试 GET 和 POST 是否正常

测试使用的是火狐的 Poster 工具。

测试 GET

测试 POST

补上一段小插曲:直接提交 POST 时是出错的:

把出错的内容粘贴出来存成html,发现是这个错误:

百度求大神,得到这样的答案:

这是从rails 2.0 开始包含的一个新功能,目的在于防止CSRF(Cross-Site Request Forgery)攻击

有这样几种解决方式

请原谅我直接暴力地选择了禁用 CSRF 的方式,找到Test/app/controllers/products_controller.rb,插入代码

  protect_from_forgery :except => :index  
  
  # you can disable csrf protection on controller-by-controller basis:  
  skip_before_filter :verify_authenticity_token  

重启 rails server

问题解决,再次提交 POST:

也就是说 Android 客户端只要能按照以上格式发送 HTTP 请求就可以了。

 

 

2 使用 Android 客户端访问 HTTP 资源

 

2.1 获取访问网络的权限

在 AndroidManifest.xml 文件中添加以下行

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

 

2.2 使用 Android 客户端提交 GET 请求

        try {
            final String url = "http://192.168.0.138:3000/products/" + message
                    + ".json";

            Thread thread = new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        HttpGet httpGet = new HttpGet(url);
                        HttpResponse httpResponse = new DefaultHttpClient()
                                .execute(httpGet);
                        if (httpResponse.getStatusLine().getStatusCode() == 200) {
                            result = EntityUtils.toString(httpResponse
                                    .getEntity());

                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            });
            thread.start();
            thread.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

 

2.3 使用 Android 客户端提交 POST 请求

try{
        Thread threadPost = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    final String url = "http://192.168.0.138:3000/products";
                    HttpPost httpPost = new HttpPost(url);
                    
                    JSONObject json = new JSONObject();
                    json.accumulate("reference", "888");
                    json.accumulate("quantity", "8");
                    JSONObject response = null;
                    StringEntity s = new StringEntity(json.toString());
                    s.setContentEncoding("UTF-8");
                    s.setContentType("application/json");
                    httpPost.setEntity(s);
                    
                    HttpResponse httpResponse = new DefaultHttpClient()
                            .execute(httpPost);
                    if (httpResponse.getStatusLine().getStatusCode() == 200) {
                        result = EntityUtils.toString(httpResponse.getEntity());
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
        threadPost.start();
        threadPost.join();
        } catch (Exception e) {
            e.printStackTrace();
        }