接触Android有半年了,一直啃不下也不敢去触碰的一块儿硬骨头就是客户端与服务端的通信。
上一篇文章写了通过谷歌官方通信框架Volly实现手机号码归属地查询,但这并不是真真意义上的掌握客户端与服务端之间的数据交换,
因为服务端是调用了由聚合网提供的一个接口API,所以这次我尝试使用eclipse亲手搭建自己的web服务器并实现一个简单的登录功能。
本文实现了Volley框架的get/post以及java原生类HttpURLConnection的get/post方式进行数据请求。
由于我是超级菜鸟型,所以本文适合超级入门级菜鸟参考,大神请无视。
话不多说,先看DEMO效果:(为简单起见,未使用数据库,只在服务端判断用户名和密码是否为admin和123)
布局文件很简单就不说了,有需要的可以私信我要源码。
package com.fukang.servertest;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.json.JSONException;
import org.json.JSONObject;
/**
* Android服务端开发,简单的web servlet实例
*
* @author fk 2015.08.11
*/
@WebServlet("/MyServlet")
public class MyServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
String name = null;
String password = null;
protected void doGet(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/json;charset=utf-8");
response.setCharacterEncoding("utf-8");
String name = request.getParameter("name");
String password = request.getParameter("password");
String id = request.getParameter("id");//测试httpPost方法能否传递多个参数
JSONObject result = getResult(name, password);
PrintWriter out = response.getWriter();
out.print(result.toString());
out.flush();
out.close();
}
protected void doPost(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
protected JSONObject getResult(String name, String password) {
JSONObject result = new JSONObject();
if ((name.equals("admin")) && (password.equals("123"))) {
try {
result.put("result", "true");
} catch (JSONException e) {
e.printStackTrace();
}
} else {
try {
result.put("result", "false");
} catch (JSONException e) {
e.printStackTrace();
}
}
return result;
}
}
package com.fukang.servertestclient;
import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import org.json.JSONException;
import org.json.JSONObject;
import android.app.Activity;
import android.graphics.Color;
import android.os.AsyncTask;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import com.android.volley.AuthFailureError;
import com.android.volley.Request.Method;
import com.android.volley.RequestQueue;
import com.android.volley.Response;
import com.android.volley.Response.Listener;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.StringRequest;
import com.android.volley.toolbox.Volley;
public class MainActivity extends Activity implements OnClickListener {
EditText et_name; // 用户名输入框
EditText et_password;// 用户密码输入框
Button btn_volleyGet; // 四种登录按钮控件
Button btn_volleyPost;
Button btn_httpGet;
Button btn_httpPost;
TextView tv_result; // 显示登录结果文本框
String name; // 登录用户名
String password;// 登录密码
// Activity被加载时调用该方法
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);// 加载布局资源
initView();// 绑定布局资源中的控件
ClickListener();// 设置按钮监听器
}
// 初始化布局资源,绑定控件
private void initView() {
et_name = (EditText) findViewById(R.id.et_name);// 获取输入的用户名及密码
et_password = (EditText) findViewById(R.id.et_password);
btn_volleyGet = (Button) findViewById(R.id.btn_VolleyGet); // 绑定不同的登录按钮控件资源
btn_volleyPost = (Button) findViewById(R.id.btn_VolleyPost);
btn_httpGet = (Button) findViewById(R.id.btn_HttpGet);
btn_httpPost = (Button) findViewById(R.id.btn_HttpPost);
tv_result = (TextView) findViewById(R.id.tv_result);// 用于显示结果
}
// 设置按钮点击事件
@Override
public void onClick(View v) {
name = et_name.getText().toString();
password = et_password.getText().toString();
switch (v.getId()) {
case R.id.btn_HttpGet:
login_httpGet(name, password);// 调用login_httpGet方法
break;
case R.id.btn_HttpPost:
login_httpPost(name, password);// 调用login_httpPost方法
break;
case R.id.btn_VolleyGet:
login_volleyGet(name, password);// 调用login_volleyGet方法
break;
case R.id.btn_VolleyPost:
login_volleyPost(name, password);// 调用login_volleyPost方法
break;
}
}
// 设置按钮点击监听器
private void ClickListener() {
btn_httpGet.setOnClickListener(this);
btn_httpPost.setOnClickListener(this);
btn_volleyGet.setOnClickListener(this);
btn_volleyPost.setOnClickListener(this);
}
// volleyGet方式请求数据
private void login_volleyGet(String name, String password) {
RequestQueue queues = Volley.newRequestQueue(getApplicationContext());// Volley框架必用,实例化请求队列
String url = "http://192.168.0.31:8080/ServerTest/MyServlet?" + "name="
+ name + "&password=" + password;// 请求url
StringRequest request = new StringRequest(Method.GET, url, // StringRequest请求
new Listener() {
@Override
public void onResponse(String arg0) {// 成功得到响应数据
try {
JSONObject result_jo = new JSONObject(arg0);
String result = result_jo.getString("result");// 取出result值
if (result.equals("true")) {
tv_result.setText("volley_get请求登陆成功!");
tv_result.setTextColor(Color
.parseColor("#66CC00"));
} else {
tv_result.setText("volley_get请求登陆失败!");
tv_result.setTextColor(Color
.parseColor("#FF0033"));
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {// 未成功得到响应数据
@Override
public void onErrorResponse(VolleyError arg0) {
tv_result.setText(arg0.toString());
}
});
request.setTag("volleyGet");// 设置请求标签Tag
queues.add(request);// 将请求加入队列queue中处理
}
// volleyPost方式请求数据
private void login_volleyPost(String username, String userpass) {
final String name = username;
final String password = userpass;
final String url = "http://192.168.0.31:8080/ServerTest/MyServlet";// post不加参数
RequestQueue queue = Volley.newRequestQueue(getApplicationContext());
StringRequest request = new StringRequest(Method.POST, url,
new Listener() {
@Override
public void onResponse(String arg0) {
try {
JSONObject result_jo = new JSONObject(arg0);
String result = result_jo.getString("result");
if (result.equals("true")) {
tv_result.setText("volley_post请求登陆成功");
tv_result.setTextColor(Color
.parseColor("#66CC00"));
} else {
tv_result.setText("volley_post请求登陆失败");
tv_result.setTextColor(Color
.parseColor("#FF0033"));
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError arg0) {
tv_result.setText(arg0.toString());
}
}) {
// 此处要实现getParams()方法来添加参数
@Override
protected Map getParams() throws AuthFailureError {
Map map = new HashMap();
map.put("name", name);
map.put("password", password);
return map;
}
};
request.setTag("volleyPost");
queue.add(request);
}
// httpGet方式请求数据
private void login_httpGet(String name, String password) {
LoginTaskGet loginTask = new LoginTaskGet();// 实例化异步任务处理类进行请求
loginTask.execute(name, password);// 传入参数,执行请求
}
// httpPost方式请求数据
private void login_httpPost(String name, String password) {
LoginTaskPost loginTask = new LoginTaskPost();
String id = UUID.randomUUID().toString();// 随机产生一个id变量,测试能否post发送三个以上参数
loginTask.execute(name, password, id);// 变量个数不限,类型要统一,以逗号隔开即可
}
/**
* 内部类,异步任务处理类。 高版本中,网络连接请求不能在UI线程中执行,需要调用该异步任务处理类。 此处为处理httpGet请求任务。
*
* @author fk 2015.08.12
*/
class LoginTaskGet extends AsyncTask {
/*
* @ 必须重写方法之一,用于异步处理网络请求!
*
* @ 取参时,可以使用传入时的参数名,也可以使用param[index]索引值!
*
* @ 对网络的请求操作都需要放在此方法中,对UI的操作尽量不要放在此方法中!
*/
@Override
protected String doInBackground(String... params) {
String result_json = null;
// String urlPath = "http://192.168.0.31:8080/ServerTest/MyServlet?"
// + "name=" + params[0] + "&password=" + params[1];
// 上面这种取参方法也可以
String urlPath = "http://192.168.0.31:8080/ServerTest/MyServlet?"
+ "name=" + name + "&password=" + password;
try {
URL url = new URL(urlPath); // 实例化URL对象,传入urlPath
HttpURLConnection conn = (HttpURLConnection) url
.openConnection(); // 通过url打开一个HttpURLConnection连接对象
if (conn.getResponseCode() == 200) { // 连接成功时响应码为200
BufferedReader br = new BufferedReader(
new InputStreamReader(conn.getInputStream()));
StringBuffer sb = new StringBuffer();
String temp = "";
while ((temp = br.readLine()) != null) {
sb.append(temp);// 依次读取响应输入流,并存入StringBuffer中
}
br.close();
conn.disconnect();// 断开连接
result_json = sb.toString();// 得到String类型的响应json
}
} catch (Exception e) {
System.out.println("error!");
}
return result_json;// 将此响应json传递到onPostExecute方法中进行UI线程的操作
}
/*
* @ 此方法虽未要求必须实现,但一般都需实现,用于处理响应结果,对UI线程操作。
*/
@Override
protected void onPostExecute(String result_json) {
try {
JSONObject jo = new JSONObject(result_json); // 根据响应json实例化json对象
String result = jo.getString("result");// 取出json对象中的返回结果result值
if (result.equals("true")) {// 判断登录是否成功
tv_result.setText("http_get请求登录成功!");
tv_result.setTextColor(Color.parseColor("#66CC00"));
} else {
tv_result.setText("http_get请求登录失败!");
tv_result.setTextColor(Color.parseColor("#FF0033"));
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}
/**
* 内部类,异步任务处理类。 高版本中,网络连接请求不能在UI线程中执行,需要调用该异步任务处理类。 此处为处理httpGet请求任务。
*
* @author fk 2015.08.12
*/
class LoginTaskPost extends AsyncTask {
String resultJson = "";
@Override
protected String doInBackground(String... params) {
String urlPath = "http://192.168.0.31:8080/ServerTest/MyServlet";// post方式不需参数
try {
URL url = new URL(urlPath);
HttpURLConnection conn = (HttpURLConnection) url
.openConnection();
conn.setUseCaches(false);// post方式需要:禁止使用缓存
conn.setDoInput(true);// post方式需要:允许输入数据
conn.setDoOutput(true);// post方式需要:允许输出数据
conn.setRequestMethod("POST");// post方式需要:设置请求方式
conn.setInstanceFollowRedirects(true);// post方式需要:连接遵循重定向
conn.setRequestProperty("Content-Type",// post方式需要:设置请求头部
"application/x-www-form-urlencoded");
conn.connect();// 至此才可以进行连接,注意:getInputStream()是隐式连接,也不可以
DataOutputStream dos = new DataOutputStream(
conn.getOutputStream());// 实例化输出流对象,用于写入参数
StringBuffer paramsBuffer = new StringBuffer();// 实例化StringBuffer缓冲器,用于存储参数
paramsBuffer.append("&name=" + params[0]);// 每个参数都要使用"&name"+"value"形式
paramsBuffer.append("&password=" + params[1]);
paramsBuffer.append("&id=" + params[2]);
dos.writeUTF(paramsBuffer.toString());// 使用UTF格式输出该参数
dos.flush();// 输出缓冲
dos.close();// 输出关闭
BufferedReader br = new BufferedReader(new InputStreamReader(// 接收服务端返回数据
conn.getInputStream()));
StringBuffer sb = new StringBuffer();
String temp = "";
while ((temp = br.readLine()) != null) {
sb.append(temp);
}
resultJson = sb.toString();
} catch (Exception e) {
e.printStackTrace();
}
return resultJson;// 将结果返回onPostExecute方法中对UI进行操作
}
@Override
protected void onPostExecute(String resultJson) {
try {
JSONObject jo = new JSONObject(resultJson);
String result = jo.getString("result");
if (result.equals("true")) {
tv_result.setText("http_post请求登录成功!");
tv_result.setTextColor(Color.parseColor("#66CC00"));
} else {
tv_result.setText("http_post请求登录失败!");
tv_result.setTextColor(Color.parseColor("#FF0033"));
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}
}