本文主要补充介绍jtds的查询方法,将以博主的一个实际开发程序进行说明

下图是项目的文件列表与界面效果:

        

运行效果:

  1、三个EditText对应的是单个计划的序号、品种名、数量

  2、填入三个数据后,点击“增加”,Insert到数据库中

  3、填入三个数据后,点击“修改”,根据序号,Update数据库中的品种名、数量

  4、填入序号后,点击“删除”,根据序号,Delete数据库中的一行记录

  5、点击“查询全部”,在下方GridView中显示整个表格的记录

  6、点击“清空”,三个EditText的内容清空,GridView的内容清空

数据库信息:

  1、数据库名:SYSTEM TEST

  2、用户名:sa

  3、密码:123

  4、表名:DayPlan

  5、字段1:ID,nvarchar  =>表示序号

  6、字段2:PCBA,nvarchar  =>表示品种名

  7、字段3:AMOUNT,nvarchar  =>数量

AndroidManifest.xml:

 <?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.test.androidsqltest"
android:versionCode="1"
android:versionName="1.0" > <uses-permission android:name="android.permission.INTERNET" /> <uses-sdk
android:minSdkVersion="14"
android:targetSdkVersion="21" /> <application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name=".MainActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application> </manifest>

  插入网络操作权限

strings.xml:

 <?xml version="1.0" encoding="utf-8"?>
<resources> <string name="app_name">AndroidSqlTest</string>
<string name="action_settings">Settings</string>
<string name="id">序 号:</string>
<string name="pcb">机种名:</string>
<string name="amount">数 量:</string>
<string name="insert">增加</string>
<string name="update">修改</string>
<string name="delete">删除</string>
<string name="clear">清空</string>
<string name="select">查询全部</string> </resources>

activity_main.xml:

 <RelativeLayout 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:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.test.androidsqltest.MainActivity" > <TextView
android:id="@+id/tvId"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="10dp"
android:layout_marginLeft="10dp"
android:layout_marginTop="5dp"
android:text="@string/id" /> <TextView
android:id="@+id/tvPcb"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="10dp"
android:layout_marginLeft="10dp"
android:layout_marginTop="45dp"
android:text="@string/pcb" /> <TextView
android:id="@+id/tvAmount"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="10dp"
android:layout_marginLeft="10dp"
android:layout_marginTop="85dp"
android:text="@string/amount" /> <EditText
android:id="@+id/etId"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="70dp"
android:layout_marginLeft="70dp"
android:layout_marginTop="-5dp"
android:inputType="text"
android:ems="10" > <requestFocus />
</EditText> <EditText
android:id="@+id/etPcb"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="70dp"
android:layout_marginLeft="70dp"
android:layout_marginTop="35dp"
android:inputType="text"
android:ems="10" /> <EditText
android:id="@+id/etAmount"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="70dp"
android:layout_marginLeft="70dp"
android:layout_marginTop="75dp"
android:inputType="text"
android:ems="10" /> <Button
android:id="@+id/btnInsert"
android:layout_width="80dp"
android:layout_height="40dp"
android:layout_marginStart="5dp"
android:layout_marginLeft="5dp"
android:layout_marginTop="120dp"
android:text="@string/insert" /> <Button
android:id="@+id/btnUpdate"
android:layout_width="80dp"
android:layout_height="40dp"
android:layout_marginStart="105dp"
android:layout_marginLeft="105dp"
android:layout_marginTop="120dp"
android:text="@string/update" /> <Button
android:id="@+id/btnDelete"
android:layout_width="80dp"
android:layout_height="40dp"
android:layout_marginStart="205dp"
android:layout_marginLeft="205dp"
android:layout_marginTop="120dp"
android:text="@string/delete" /> <Button
android:id="@+id/btnClear"
android:layout_width="120dp"
android:layout_height="40dp"
android:layout_marginStart="5dp"
android:layout_marginLeft="5dp"
android:layout_marginTop="180dp"
android:text="@string/clear" /> <Button
android:id="@+id/btnSelect"
android:layout_width="120dp"
android:layout_height="40dp"
android:layout_marginStart="165dp"
android:layout_marginLeft="165dp"
android:layout_marginTop="180dp"
android:text="@string/select" /> <GridView
android:id="@+id/gv"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_marginTop="240dp"
android:numColumns="1"
android:verticalSpacing="15dp" >
</GridView> </RelativeLayout>

planlist.xml:

 <?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="fill_parent" > <TextView android:id="@+id/header1"
android:layout_height="wrap_content"
android:layout_width="60px"
android:layout_marginLeft="0px"
android:textColor="#000000"
android:text="">
</TextView> <TextView android:id="@+id/header2"
android:layout_height="wrap_content"
android:layout_width="180px"
android:layout_marginLeft="0px"
android:textColor="#000000"
android:text="">
</TextView> <TextView android:id="@+id/header3"
android:layout_height="wrap_content"
android:layout_width="80px"
android:layout_marginLeft="0px"
android:textColor="#000000"
android:text="">
</TextView> </LinearLayout>

  这是GridView中单个item的布局,即一行记录有3个TextView

SqlHelper.java:

 package MyJtds;

 import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.List; import org.json.JSONArray;
import org.json.JSONObject; public class SqlHelper {
private String drive = "net.sourceforge.jtds.jdbc.Driver";
private String connStr;
private String server;
private String dbName;
private String userName;
private String userPwd;
private Connection con;
private PreparedStatement pstm; public SqlHelper(String server, String dbName, String userName, String userPwd) {
this.server = server;
this.dbName = dbName;
this.connStr = "jdbc:jtds:sqlserver://" + this.server + ":1433/" + this.dbName;
this.userName = userName;
this.userPwd = userPwd; try {
Class.forName(drive);
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} public int ExecuteNonQuery(String sql, List<Object> params) {
try {
con = DriverManager.getConnection(this.connStr, this.userName, this.userPwd);
pstm = con.prepareStatement(sql);
if (params != null && !params.equals("")) {
for (int i = 0; i < params.size(); i++) {
pstm.setObject(i + 1, params.get(i));
}
}
return pstm.executeUpdate();
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
return -1;
} finally {
try {
pstm.close();
con.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
} public String ExecuteQuery(String sql, List<Object> params) {
// TODO Auto-generated method stub
JSONArray jsonArray = new JSONArray();
try {
con = DriverManager.getConnection(this.connStr, this.userName, this.userPwd);
pstm = con.prepareStatement(sql);
if (params != null && !params.equals("")) {
for (int i = 0; i < params.size(); i++) {
pstm.setObject(i + 1, params.get(i));
}
}
ResultSet rs = pstm.executeQuery();
ResultSetMetaData rsMetaData = rs.getMetaData();
while (rs.next()) {
JSONObject jsonObject = new JSONObject();
for (int i = 0; i < rsMetaData.getColumnCount(); i++) {
String columnName = rsMetaData.getColumnLabel(i + 1);
String value = rs.getString(columnName);
jsonObject.put(columnName, value);
}
jsonArray.put(jsonObject);
}
return jsonArray.toString();
} catch (Exception e) {
// TODO: handle exception
return null;
} finally {
try {
pstm.close();
con.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}

Plan.java:

 package Models;

 public class Plan {
public String id; public String pcb; public String amount; public String getId() {
return id;
} public void setId(String id) {
this.id = id;
} public String getPcb() {
return pcb;
} public void setPcb(String pcb) {
this.pcb = pcb;
} public String getAmount() {
return amount;
} public void setAmount(String amount) {
this.amount = amount;
}
}

MainActivity.java:

 package com.test.androidsqltest;

 import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map; import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken; import Models.Plan;
import MyJtds.SqlHelper;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.GridView;
import android.widget.SimpleAdapter;
import android.widget.Toast; public class MainActivity extends Activity { // 定义控件
private EditText etId;
private EditText etPcb;
private EditText etAmount;
private Button btnInsert;
private Button btnUpdate;
private Button btnDelete;
private Button btnClear;
private Button btnSelect;
private GridView gv;
// 定义变量
private String id = "";
private String pcb = "";
private String amount = "";
// SQL帮助类,参数用于设置连接字符串,参数1:主机ip,参数2:数据库名,参数3:用户名,参数4:用户密码
private SqlHelper sh = new SqlHelper("192.168.1.1", "SYSTEM TEST", "sa", "123"); @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); // 找到变量,并且赋值
etId = (EditText) findViewById(R.id.etId);
etPcb = (EditText) findViewById(R.id.etPcb);
etAmount = (EditText) findViewById(R.id.etAmount);
btnInsert = (Button) findViewById(R.id.btnInsert);
btnUpdate = (Button) findViewById(R.id.btnUpdate);
btnDelete = (Button) findViewById(R.id.btnDelete);
btnClear = (Button) findViewById(R.id.btnClear);
btnSelect = (Button) findViewById(R.id.btnSelect);
gv = (GridView) findViewById(R.id.gv); // 绑定按钮的click事件监听,click事件触发后,运行clickEvent()方法
// 绑定的方式都是clickEvent(),到时在方法体中判断按下的是哪个按键
btnInsert.setOnClickListener(clickEvent());
btnUpdate.setOnClickListener(clickEvent());
btnDelete.setOnClickListener(clickEvent());
btnClear.setOnClickListener(clickEvent());
btnSelect.setOnClickListener(clickEvent());
} // clickEvent()
private OnClickListener clickEvent() {
// TODO Auto-generated method stub
return new OnClickListener() { // clickEvent()方法体,参数是控件的基类View,必须加上final
@Override
public void onClick(final View view) {
// TODO Auto-generated method stub
// 用view来判断按下的哪个按钮
if (view == btnClear) {
// ClearEdit()方法用于复位控件
ClearEdit();
} else {
// 如果不是btnClear,那就是增删改查的按钮,必须开启新的线程进行操作
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
// 通过Message类来传递结果值,先实例化
Message msg = Message.obtain();
// 下面分别是增删改查方法
if (view == btnInsert) {
// 设定msg的类型,用what属性,便于后面的代码区分返回的结果是什么类型
// 这里的1是指操作是否成功,String
// 这里的2是指查询的结果,String,用json的形式表示
msg.what = 1;
msg.obj = Insert();
} else if (view == btnUpdate) {
msg.what = 1;
msg.obj = Update();
} else if (view == btnDelete) {
msg.what = 1;
msg.obj = Delete();
} else if (view == btnSelect) {
String jsonResult = Select();
msg.what = 2;
msg.obj = jsonResult;
} else { }
// 执行完以后,把msg传到handler,并且触发handler的响应方法
handler.sendMessage(msg);
}
});
// 进程开始,这行代码不要忘记
thread.start();
}
}
};
} // Handler类用于接收Message的值,并且其父类有一个默认的handleMessage方法,用super。handleMessage()方法,传入msg,就能控制主线程的控件了
@SuppressLint("HandlerLeak")
private Handler handler = new Handler() {
public void handleMessage(Message msg) {
// 调用super的方法,传入handler对象接收到的msg对象
super.handleMessage(msg);
// 判断msg.what的值,有1和2,
// 1表示操作是否成功,2表示查询时得到的json结果
switch (msg.what) {
case 1:
// 获得执行的结果,String字符串,返回操作是否成功提示
String rst = msg.obj.toString();
// 使用气泡提示
Toast.makeText(getApplicationContext(), rst, Toast.LENGTH_SHORT).show();
break;
case 2:
// 获得查询的json结果
String jsonResult = msg.obj.toString();
// 控制台输出,用于监视,与实际使用无关
System.out.println(jsonResult); // Gson类,用于json的转类型操作
Gson gson = new Gson();
// 定义查询到的结果类型,每一行记录映射为对象,本程序查询的是生产计划,所以一行记录表示一个品种的生产计划,用Plan类表示,用List收集全部Plan类
Type type = new TypeToken<List<Plan>>() {
}.getType();
// 使用gson的fromJson()方法,参数1:json结果,参数2:想要转哪一个类型
List<Plan> plans = gson.fromJson(jsonResult, type); // 由于要使用GridView表示,绑定数据时只能使用Map<K,T>的类型,并且多个记录时,要用List<Map<K,T>>
// 先实例化
List<Map<String, String>> mPlans = new ArrayList<Map<String, String>>();
// 实例化一个title,是GridView的列头
Map<String, String> title = new HashMap<String, String>();
title.put("id", "序号");
title.put("pcb", "机种名");
title.put("amount", "计划数");
// 首先把表头追加到List<Map<String, String>>
mPlans.add(title); // for循环从json转过来的List<Plan>
for (Plan plan : plans) {
// 实例化用于接收plan的HashMap<K,T>类
HashMap<String, String> hmPlans = new HashMap<String, String>();
// 使用put()方法把数值加入到HashMap<K,T>,参数1:键,参数2:值
hmPlans.put("id", plan.id);
hmPlans.put("pcb", plan.pcb);
hmPlans.put("amount", plan.amount);
// 把HashMap加入到List<Map>中
mPlans.add(hmPlans);
} // SimpleAdapter是GridView的适配器,参数1:上下文内容,参数2:List<Map<K,T>>对象,参数3:GridView的布局文件,指每一个item的布局,需要在res/layout中创建xml,
// 参数4:String数组,指每一列要绑定到Map中的值,数组中的值就是上文“hmPlans.put("id",
// plan.id);”的键"id"
// 参数5:列头的显示文件,存放在res/values/strings.xml
SimpleAdapter sa = new SimpleAdapter(getApplicationContext(), mPlans, R.layout.planlist,
new String[] { "id", "pcb", "amount" }, new int[] { R.id.header1, R.id.header2, R.id.header3 });
// 把SimpleAdapter绑定到GridView
gv.setAdapter(sa); // 气泡提示
Toast.makeText(getApplicationContext(), "读取成功!", Toast.LENGTH_SHORT).show();
break;
default:
Toast.makeText(getApplicationContext(), "操作失败!", Toast.LENGTH_SHORT).show();
break;
}
}
}; // 用于接收EditText的输入值,并赋值到字符串
public void GetMsg() {
id = etId.getText().toString().trim();
pcb = etPcb.getText().toString().trim();
amount = etAmount.getText().toString().trim();
} // Insert()方法,通过判断受影响行数,返回“添加成功”或“操作失败”
public String Insert() {
String sql = "INSERT INTO [DayPlan]([ID],[PCBA],[AMOUNT]) VALUES (?,?,?)";
GetMsg();
List<Object> params = new ArrayList<Object>();
params.add(id);
params.add(pcb);
params.add(amount);
try {
int count = sh.ExecuteNonQuery(sql, params);
if (count == 1) {
return "添加成功!";
} else {
return "操作失败!";
}
} catch (Exception e) {
// TODO Auto-generated catch block
System.out.println(e.getMessage());
return "操作失败!";
}
} public String Update() {
String sql = "UPDATE [DayPlan] SET [PCBA]=?,[AMOUNT]=? where [ID]=?";
GetMsg();
// params用于存放变量参数,即sql中的“?”
List<Object> params = new ArrayList<Object>();
params.add(pcb);
params.add(amount);
params.add(id);
try {
int count = sh.ExecuteNonQuery(sql, params);
if (count == 1) {
return "更新成功!";
} else {
return "操作失败!";
}
} catch (Exception e) {
// TODO: handle exception
System.out.println(e.getMessage());
return "操作失败!";
}
} public String Delete() {
String sql = "DELETE FROM [DayPlan] where [ID]=?";
GetMsg();
List<Object> params = new ArrayList<Object>();
params.add(id);
try {
int count = sh.ExecuteNonQuery(sql, params);
if (count == 1) {
return "删除成功!";
} else {
return "操作失败!";
}
} catch (Exception e) {
// TODO: handle exception
System.out.println(e.getMessage());
return "操作失败!";
}
} // Select()方法,查询生产计划
public String Select() {
String sql = "SELECT [ID] AS id,[PCBA] AS pcb,[AMOUNT] AS amount FROM [DayPlan] ORDER BY id";
String jsonResult = null;
try {
// sh.ExecuteQuery(),参数1:查询语句,参数2:查询用到的变量,用于本案例不需要参数,所以用空白的new
// ArrayList<Object>()
jsonResult = sh.ExecuteQuery(sql, new ArrayList<Object>());
} catch (Exception e) {
// TODO: handle exception
System.out.println(e.getMessage());
return null;
}
return jsonResult;
} // 界面复位,清空显示
public void ClearEdit() {
//清空文本输入框
etId.setText("");
etPcb.setText("");
etAmount.setText("");
//etId获得焦点
etId.setFocusable(true);
etId.setFocusableInTouchMode(true);
etId.requestFocus();
etId.requestFocusFromTouch();
//清空GridView的绑定值
gv.setAdapter(null);
} @Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
} @Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
}

完成。

Android 连接 SQL Server (jtds方式)——下的更多相关文章

  1. Android 连接 SQL Server (jtds方式)——上

    本文将介绍开发Android程序,连接SQL Server,通过第三方包jtds的方式. 如果你有同样的需求,请跟着做一遍,博主将以最详细的方式,进行介绍. 首先说明,Java.Android连接SQ ...

  2. Android 连接网络数据库的方式

    以连接MS SQL(sqlserver数据库)的网络数据库为例,从当前搜集的资料来看,一共有两种方式:在Android工程中引入JDBC驱动,直接连接:通过WebService等方法的间接连接. 采用 ...

  3. 【原创】Qt 使用ODBC driver 连接SQL Server

    最近在做数据库的课程设计.第一个需要解决的问题是使用什么工具来实现这个系统.经过一番资料查找,决定使用SQL Server Express 2012作为服务器,使用Qt作为编写客户端程序语言.问题是c ...

  4. jTDS Java连接SQL Server 2000数据库

    Java连接SQL Server 2000数据库时,有两种方法: (1)通过Microsoft的JDBC驱动连接.此JDBC驱动共有三个文件,分别 是mssqlserver.jar.msutil.ja ...

  5. Java连接SQL Server:jTDS驱动兼容性问题

    Java连接SQL Server 2000数据库时,有两种方法: (1)通过Microsoft的JDBC驱动连接.此JDBC驱动共有三个文件,分别是mssqlserver.jar.msutil.jar ...

  6. ASP .Net Core 在 CentOS8 ARM 下连接 SQL Server 2008 R2(Hypervisor)

    本文主要记录在 ARM 系统下无法连接SQL Server 2008 R2 的解决过程. 解决方案是使用 ODBC 的方式连接数据库,进行操作. 手上有公司的华为鲲鹏云计算 ARM 架构的 CentO ...

  7. phpstudy连接SQL Server 2008数据库 以及 php使用sql server出现乱码解决方式

    开始也尝试自己配置php安装环境,找到一个详细的百度经验http://jingyan.baidu.com/article/154b46315242b328ca8f4101.html,前面有问题也一一去 ...

  8. Ubuntu下erlang连接SQL SERVER 2008

    erlang连接SQL Server使用ODBC方法,但在网络上还是缺少资料,自己折腾了2天才成功.现在特记录下来,以供大家借鉴. 基本思路是 erlang odbcserver + unixodbc ...

  9. JeeSite如何正确连接SQL SERVER 数据库

    JeeSite如何正确连接SQL SERVER 数据库 jeesite介绍 感谢jeesite项目的作者thinkgem. 没有你我也不会更改这数据源非了恁大的劲,,,,嘻嘻嘻说多了. JeeSite ...

随机推荐

  1. 原生JS写Ajax的请求函数

    一.JS原生ajax ajax:一种请求数据的方式,不需要刷新整个页面:ajax的技术核心是 XMLHttpRequest 对象:ajax 请求过程:创建 XMLHttpRequest 对象.连接服务 ...

  2. 转:《IIC时序》

    I2C(Inter-Integrated Circuit)总线是一种由PHILIPS公司开发的两线式串行总线,用于连接微控制器及其外围设备.I2C总线产生于在80年代,最初为音频和视频设备开发,如今主 ...

  3. 【技术贴】解决前台js传参中文乱码

    方法1: 前台两次编码,后台一次解码.因为getParamet已经自动解了一次了. JavaScript: window.self.location="list.jsp?searchtext ...

  4. centos6.5安装gcc6.1等c++环境

    centos6.5安装gcc6.1等c++环境 1.获取gcc安装包并解压wget http://ftp.gnu.org/gnu/gcc/gcc-6.1.0/gcc-6.1.0.tar.bz2tar ...

  5. Codeforces Round #316 (Div. 2)

    A. Elections time limit per test 1 second memory limit per test 256 megabytes input standard input o ...

  6. 如何在svn系统中使用git

    如果正在使用svn,打算换到git,又暂时不想放弃已有的svn代码库,可以选择git-svn.说一说我自己从svn到git的经验吧. 开始 安装最新版本的git,从git 1.5.3以后支持git-s ...

  7. 【模拟】NEERC15 G Generators(2015-2016 ACM-ICPC)(Codeforces GYM 100851)

    题目链接: http://codeforces.com/gym/100851 题目大意: n个序列.每个序列有4个值x,a,b,c,之后按照x=(a*x+b)%c扩展无穷项. 求每个序列各取一个数之后 ...

  8. HDOJ(HDU) 2132 An easy problem

    Problem Description We once did a lot of recursional problem . I think some of them is easy for you ...

  9. 《JavaScript语言精髓与编程实践》读书笔记二

    第3章非函数式语言特性 这一章首先介绍了语言的分类,命令式(结构化编程,面向对象编程),说明式(函数式等).而这一章,主要介绍JS的非函数式特点. 在开始之前,首先介绍了由“结构化编程”向“面向对象编 ...

  10. Jenkins 一: 环境安装以及配置

    安装JDK 下载地址: http://www.oracle.com/technetwork/java/javase/downloads/index.html 选择的JDK版本和开发使用的JDK版本最好 ...