使用 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(); }