在 IBM Bluemix™ 中开发应用程序非常容易,这不是什么秘密。企业开发人员现在对使用 Bluemix 创建 “模型-视图-控制器(MVC)” 风格的移动应用程序非常感兴趣。本教程使用了一个简单的商业案例,向您展示如何使用 MVC 风格的架构在 Bluemix 中设计和开发应用程序。在开始构建之前,我们会介绍一些基础知识。
MVC 是用来开发用户界面的最常用的功能强大的架构模式。MVC 架构模式是将应用程序分成以下三个部分的一种方式:模型、视图和控制器。视图负责管理来自用户的图形和文字输入。控制器负责解释来自用户的输入以及模型或视图要更改的命令(视情况而定)。模型负责管理应用程序的行为和数据,并响应指令(通常来自控制器),以便更改状态。在本教程中,我们采用了 MVC 架构风格来构建移动应用程序。
RESTful Web 服务是一些满足具象状态传输 (REST) 架构约束条件的 API。它们不要求客户端了解关于 API 结构的任何事情。浏览器不会预先获得关于要将元数据提交到何处以及提交哪些元数据的信息。服务器向客户端提供了必要的信息,比如 URI 和所需的字段,以便成功完成 API 调用。我们在样例应用程序的服务层中使用了 RESTful Web 服务。
“ 始终使用 MVC。明确将业务逻辑与控制器逻辑和表象区分开来。良好的分层可以减少很多错误。 ”
- The top Java EE best practices
Bluemix Dairy Production Center 是一个研究所,可以使用相关技术和知识帮助牛奶生产商优化牛奶生产。牛奶生产商会获得经过 Dairy Production Center 分析和测试的奶牛,并收到关于每年的挤奶顺序和疾病控制的分析和建议。在执行分析期间,Dairy Production Center 想为牛奶生产商提供一种方式来查看有关其奶牛、牧群、挤奶顺序和疾病的信息。牛奶生产商能够发送和接收来自 Dairy Production Center 的新闻。
利用我们的简单的移动应用程序,牛奶生产商可以查看他们在 Dairy Production Center 中看到的相关信息。
设计该应用程序的时候使用了 MVC 风格的架构。
点击查看大图
关闭 [x]
MVC 组件包括:
样例 Dairy Production Center 移动应用程序能够与 Bluemix 中暴露的 Dairy Production Center RESTful API 调用进行交互。该应用程序发布了任何外部客户端可以通过 HTTP 协议进行使用的 API。然后,牛奶生产商会有一个允许用户登录的移动应用程序:
查看奶牛列表和可用于奶牛的牧群的列表,并向 Dairy Production Center 传递消息。
运行应用程序
获取代码
阅读: Android 应用程序开发
要构建数据访问层,可以使用以下这些步骤创建数据库、模式、表、关系、数据和数据访问对象:
点击查看大图
关闭 [x]
点击查看大图
关闭 [x]
现在是时候来查看用来开发数据访问层的代码了。
这一层中使用的主要数据访问对象是:
DAO 包下的列所组成的列表如下所示:
public Connection getConnnection() throws SQLException{ Connection con = null; try { DB2SimpleDataSource dataSource = new DB2SimpleDataSource(); dataSource.setServerName(databaseHost); dataSource.setPortNumber(port); dataSource.setDatabaseName(databaseName); dataSource.setUser(user); dataSource.setPassword (password); dataSource.setDriverType(4); con=dataSource.getConnection(); con.setAutoCommit(false); } catch (SQLException e) { throw new SQLException(); } return con; }
下一个任务是使用 DAO 从数据库表 (DP_COWS) 中为生产商检索所有奶牛。
以下代码展示了如何从数据库中为生产商检索奶牛列表。执行以下方法从数据库中检索这些数据值:
public ArrayList<Cow> getAllCows(String prodid){ ArrayList<Cow> cwArraylist = new ArrayList<Cow>(); System.out.println("Inside Get All Cows" + prodid); Connection conn = null; try { conn = new DairyProductionCenterDBConnection().getConnnection(); String tableName = ""; String sqlStatement = ""; String schemaName = "IBM_ECOD_DAIRYPRODUCTIONCENTER"; tableName = schemaName + "." + "DP_COWS"; Statement stmt = conn.createStatement(); sqlStatement = "SELECT * FROM " + tableName + " WHERE PRODUCER_ID = " + "'" + prodid + "'"; ResultSet rs = stmt.executeQuery(sqlStatement); while (rs.next()) { Cow cw = new Cow(rs.getString("COW_ID"), rs.getString("RFTAG_ID"), rs.getString("HERD_ID"), rs.getString("REPORT_COMMENTS"), rs.getString("COW_NAME")); cwArraylist.add(cw); } rs.close(); stmt.close(); }catch (SQLException e) { return null; } finally { try { conn.close(); } catch (Exception e) { /* ignored */ } } return cwArraylist; }
您会在数据库表 (DP_COWS) 中看到某个生产商的奶牛列表数据:
奶牛列表
点击查看大图
关闭 [x]
创建一个服务层,该服务层将会调用数据服务层(模型),并向外部客户端发布 RESTful 服务。这一节将重点介绍如何构建和发布 CowList REST 服务,我们已经构建了数据访问层。REST 服务调用将通过调用数据访问层(如包结构中提到的那样)和下方的类来检索奶牛列表。
这一层是使用 Apache Wink REST 服务框架和 Java JSON Builder layer 实用工具实现的。用来开发 RESTful 服务调用的包和类如下所示:
@Path("/dairyproductioncenterapi") public class DairyProductionCenterRestAPIs{ DairyProductionCenterDAO dpcDao = new DairyProductionCenterDAOImpl(); @Context HttpServletRequest request; @GET @Path("/producer/{prodid}/cows") @Produces(MediaType.APPLICATION_JSON) public Response getCows(@PathParam("prodid") String prodid){ System.out.println("Getting All Cows for----" + prodid); ArrayList<Cow> cw = dpcDao.getAllCows(prodid); if (cw.size() > 0) { return Response.ok(JsonBuilderUtils.constructCowJSON(cw)).build(); } else { return Response.ok(JsonBuilderUtils.constructCowJSON(cw)).build(); } }
来显示 RESTful 服务调用及其结果。
比较 JSON 响应数据与数据库中的数据,如List of Cows中所示。
https://bluemixdairyproductioncenter.mybluemix.net/rest/dairyproductioncenterapi/producer/PROD1/cows
点击查看大图
关闭 [x]
表示层中的简单 Android 应用程序用于查看生产商的奶牛列表,该操作是使用前面小节中创建的服务和数据访问层来实现的。要构建移动应用程序,可以使用 Android Development ToolKit (ADT)。要调用 REST 服务调用,可以使用 Apache HTTP 客户端框架。
protected Boolean doInBackground(final String... args) { // Creating service handler class instance RESTInvoker sh = new RESTInvoker(); System.out.println("URL in cowlist-------" + url); // Making a request to url and getting response String jsonStr = sh.makeServiceCall(url, RESTInvoker.GET); Log.d("Response: ", "> " + jsonStr); return true; } //RESTInvoker public String makeServiceCall(String url, int method, List<NameValuePair> params) { try { // http client DefaultHttpClient httpClient = new DefaultHttpClient(); HttpEntity httpEntity = null; HttpResponse httpResponse = null; //Checking http request method type if (method == POST) { HttpPost httpPost = new HttpPost(url); if (params != null) { httpPost.setEntity(new UrlEncodedFormEntity(params)); } httpResponse = httpClient.execute(httpPost); } else if (method == GET) { // appending params to url if (params != null) { String paramString = URLEncodedUtils .format(params, "utf-8"); url += "?" + paramString; System.out.println("URL in Service Handler ----" + url); } System.out.println("URL in Service Handler ----" + url); HttpGet httpGet = new HttpGet(); URI website = new URI(url.trim()); httpGet.setURI(website); httpResponse = httpClient.execute(httpGet); } httpEntity = httpResponse.getEntity(); response = EntityUtils.toString(httpEntity); System.out.println("Response from Output Cow Rest call----" + response); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } catch (ClientProtocolException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } catch (URISyntaxException e) { // TODO Auto-generated catch block e.printStackTrace(); } return response; }
if (jsonStr != null) { JSONObject jsonObj = new JSONObject(jsonStr); System.out.println("JSONString in After converting to JSON Object -------" + jsonObj); // Getting JSON Array node cows = jsonObj.getJSONArray(TAG_COWS); // looping through All Cows for (int i = 0; i < cows.length(); i++) { JSONObject c = cows.getJSONObject(i); System.out.println("JSONString Inside i loop -------" + c); String rfid = c.getString(TAG_RFID); String cowname = c.getString(TAG_COWNAME); String cowid = c.getString(TAG_COWID); String herdid = c.getString(TAG_HERDID); String report = c.getString(TAG_REPORT); // tmp hashmap for single contact HashMap<String, String> cows = new HashMap<String, String>(); // adding each child node to HashMap key => value cows.put(TAG_COWID, cowid); cows.put(TAG_RFID, rfid); cows.put(TAG_HERDID, herdid); cows.put(TAG_REPORT, report); // adding contact to contact list cowsList.add(cows); } }
protected void onPostExecute(final Boolean success) { // Dismiss the progress dialog if (pDialog.isShowing()){ pDialog.dismiss(); } /** * Updating parsed JSON data into ListView * */ ListAdapter adapter = new SimpleAdapter(context, cowsList, R.layout.cowinfo, new String[] { TAG_COWID, TAG_RFID,TAG_HERDID,TAG_REPORT,}, new int[] { R.id.cowid, R.id.rfid, R.id.herdid,R.id.report}); setListAdapter(adapter); }
现在,编码已经完成了,您可以构建代码,并开始在 Android Emulator 中运行应用程序:
生产商的奶牛列表将会显示。
使用 Bluemix 功能构建一个 MVC 风格的移动应用程序非常简单。在规划呈现内容和呈现方式的时候,一定要了解 MVC 实现的一些基础知识;在您自己的 MVC 平台上构建应用程序时,要了解关于事件和用户输入的基础知识。Bluemix PaaS 提供了一个用户友好的平台,该平台有许多功能,比如运行时、服务和移动特性,这些功能可以帮助您快速而又轻松地构建一个 MVC 风格的应用程序。
BLUEMIX SERVICE USED IN THIS TUTORIAL: SQLDB 数据库服务 向您的应用程序添加了一个随需应变的关系数据库。受到 DB2 的支持,它提供了一个托管数据库服务来处理 Web 工作负载和事务工作负载。