android通过发送http请求与java后端进行响应

背景:最近有同学需要服务端和安卓进行交流的需求,我在大二的时侯也在想java和安卓端是如何交接的,但因为当时水平有限,所以没能解决,也是一直把这件事情埋在心中,如今也在网上找到了一种方法,这种方法是用http请求进行交流,但是原来的博主一些细节没有交代清楚,我也踩了一些坑。不过原博主的代码还是挺好的,有需求的朋友可在原代码上进行拓展,如连接数据库、将数据显示到网页上。解决了安卓和java服务端的交接问题,这些拓展都是很容易去实现。这是原博主的博客原文http://blog.csdn.net/u012145166/article/details/51335187,下面我复制的代码的时候,我会把我遇到的坑一并介绍。这是源代码,直接到github上下载即可https://github.com/duantuigegelxh/AndroidAndJava。我使用的开发软件分别为idea和andorid stodio。

服务端:

user这是一个javaBean类,在服务端和客户端分别有一个。

package bean;

import java.io.Serializable;
import java.util.Date;

/**
 * JavaBean ,存储User上的 信息
 */
public class User implements Serializable{
	private int id;
	private String phoneNumber;
	private String password;
	private String userName;
	private String emailAddress;
	private Date registerTime;
	//用于URL传参和取参时的key
	public static String PHONENUMBER = "phoneNumber";
	public static String PASSWORD = "passWord";
	public static String USERNAME = "userName";
	//构造函数
	public User(String phoneNumber,String password,String userName){
		this.phoneNumber = phoneNumber;
		this.password = password;
		this.userName = userName;
		registerTime = new Date();
	}
	
	public User() {
		
	}
	
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public String getPhoneNumber() {
		return phoneNumber;
	}
	public void setPhoneNumber(String phoneNumber) {
		this.phoneNumber = phoneNumber;
	}
	public String getPassword() {
		return password;
	}
	public void setPassword(String password) {
		this.password = password;
	}
	public String getUserName() {
		return userName;
	}  
	public void setUserName(String userName) {
		this.userName = userName;
	}
	public String getEmailAddress() {
		return emailAddress;
	}
	public void setEmailAddress(String emailAddress) {
		this.emailAddress = emailAddress;
	}
	public Date getRegisterTime() {
		return registerTime;
	}
	public void setRegisterTime(Date registerTime) {
		this.registerTime = registerTime;
	}
	
}

Dao层,这里是模拟从数据库里面取数据,自己可拓展与数据库连接实现增删改查等。

package bean;

import java.util.ArrayList;

/**
 *这个是模拟数据库的DAO层,如果用户和下面的phoneNumber(123456),password(abc123456)如果是一样的,就说明前端
 * 传过来的数据是一样的,这个以后拓展成访问数据库
 */
public class UserDAO {
	public static void main(String[] args) {
		UserDAO userDAO = new UserDAO();
		System.out.println(userDAO.isLoginOK("123456", "abc123456"));
	}
	public ArrayList<User> users;
			
	public UserDAO() {
		//这个相当于从数据库中查数据,可以自己拓展连接数据库,然后根据sql语句进行增删改查
		// TODO Auto-generated constructor stub
		users = new ArrayList<User>();
		//这个相当于从数据库里面取到的数据,相当于之前注册了两个用户
		users.add(new User("123456","abc123456","codingma"));
		users.add(new User("654321","abcdf123","codemayq"));
	}


	/**
	 * 这个是验证登录信息是否正确的方法
	 * @param phoneNumber
	 * @param password
	 * @return
	 */
	public boolean isLoginOK(String phoneNumber,String password) {
		for (User user : users) {
			if (user.getPhoneNumber().equals(phoneNumber)) {
				if (user.getPassword().equals(password)) {
					return true;
				}
			}
		}
		return false;
	}
}

 

servlet类,因为我使用了@WebSerlvet注解,所以可以不用在web.xml里面配置servlet

package servlet;

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 bean.User;
import bean.UserDAO;


/**
 * 这个是一个Servlet类
 *
 * @WebServlet("/loginServlet")相当于在web.xml里面配置了servlet,这是一个注解
 */
@WebServlet("/loginServlet")
public class LoginServlet extends HttpServlet {

	/**
	 * Constructor of the object.
	 */
	public LoginServlet() {
		super();
	}

	/**
	 * The doGet method of the servlet. <br>
	 *这个方法应该是作者用来测试这个servlet是否可行而编写的业务逻辑
	 * This method is called when a form has its tag value method equals to get.
	 * 
	 * @param request the request send by the client to the server
	 * @param response the response send by the server to the client
	 * @throws ServletException if an error occurred
	 * @throws IOException if an error occurred
	 */
	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {

		response.setContentType("text/html");
		PrintWriter out = response.getWriter();
		out.println("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">");
		out.println("<HTML>");
		out.println("  <HEAD><TITLE>A Servlet</TITLE></HEAD>");
		out.println("  <BODY>");
		out.print("    This is ");
		out.print(this.getClass());
		out.println(", using the GET method");
		out.println("  </BODY>");
		out.println("</HTML>");
		out.flush();
		out.close();
	}

	/**
	 * The doPost method of the servlet. <br>
	 *
	 * This method is called when a form has its tag value method equals to post.
	 * 
	 * @param request the request send by the client to the server
	 * @param response the response send by the server to the client
	 * @throws ServletException if an error occurred
	 * @throws IOException if an error occurred
	 */
	public void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {

		response.setContentType("text/html");
		PrintWriter out = response.getWriter();

		//这两个是获得android端传过来的数据
		String phoneNumber = request.getParameter(User.PHONENUMBER);
		String passWord = request.getParameter(User.PASSWORD);

		
		//这个是初始化这个UserDao类,会先调用无参构造器
		UserDAO userDAO = new UserDAO();

		//OK和Wrong会在安卓端被接收到用来判断服务端是否通过了验证
		if (userDAO.isLoginOK(phoneNumber, passWord)) {
			out.println("OK");
		}else {
			out.println("Wrong");
		}
		
		out.flush();
		out.close();
	}

}

 

安卓客户端(安卓我不太懂,如有错误,欢迎斧正)

布局:activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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:gravity="center_horizontal|center_vertical"
    android:orientation="vertical"
    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.pku.codingma.zhisms.ui.loginAndRegister.LoginActivityFragment"
    tools:showIn="@layout/activity_main">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">
        <TextView
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:text="手机号:"
            android:inputType="phone"
            android:layout_weight="1"/>

        <EditText
            android:id="@+id/phoneNumberEditText"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="5"/>

    </LinearLayout>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">

        <TextView
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:text="密码:"
            android:layout_weight="1"/>

        <EditText
            android:id="@+id/passwordEditText"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:inputType="textPassword"
            android:layout_weight="5"/>

    </LinearLayout>

    <Button
        android:id="@+id/loginButton"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="12dp"
        android:background="@color/colorPrimaryDark"
        android:text="login"/>

</LinearLayout>

AndroidManifest.xml,这里需要加 <uses-permission android:name="android.permission.INTERNET"/>和android:usesCleartextTraffic="true",至于原因在下面说明了,否则会出现异常。

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.asus.httpcallbacklistener">

    <!--
    解决Cleartext HTTP traffic to XXX not permitted问题,
    为保证用户数据和设备的安全,Google针对下一代 Android 系统(Android P) 的应用程序,将要求默认使用加密连接,这意味着 Android P 将禁止 App 使用所有未加密的连接,因此运行 Android P 系统的安卓设备无论是接收或者发送流量,未来都不能明码传输,需要使用下一代(Transport Layer Security)传输层安全协议,而 Android Nougat 和 Oreo 则不受影响。

作者:周大侠侠侠侠侠侠侠侠侠侠侠侠侠
链接:https://www.jianshu.com/p/fd0b0fd0e34c
来源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。
    -->
    <uses-permission android:name="android.permission.INTERNET"/>

    <!--android:usesCleartextTraffic="true" 解决  java.net.SocketException: socket failed: EACCES (Permission denied)

       因为使用okhttp需要获取网络权限,所以需要在manifest中加入网络权限
    -->
    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"


        android:usesCleartextTraffic="true"


        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

 

 HttpCallbackListener.java,这个接口会在下面以匿名内部类的方式实现其业务逻辑

package com.example.asus.httpcallbacklistener;

//请求回调接口
public interface HttpCallbackListener {

    void onFinish(String response);

    void onError(Exception e);
}

HttpUtil,使用http请求和java服务端连接的工具类

package com.example.asus.httpcallbacklistener;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.Map;

/**
 * 发送http的工具类
 */

public class HttpUtil {
    //封装的发送请求函数
    public static void sendHttpRequest(final String address, final HttpCallbackListener listener) {
        if (!HttpUtil.isNetworkAvailable()){
            //这里写相应的网络设置处理
            return;
        }
        new Thread(new Runnable() {
            @Override
            public void run() {
                HttpURLConnection connection = null;
                try{
                    URL url = new URL(address);
                    //使用HttpURLConnection
                    connection = (HttpURLConnection) url.openConnection();
                    //设置方法和参数
                    //请求方法
                    connection.setRequestMethod("GET");
                    //连接超时时间
                    connection.setConnectTimeout(8000);
                    //读取超时异常
                    connection.setReadTimeout(8000);

                    connection.setDoInput(true);
                    connection.setDoOutput(true);
                    //获取返回结果
                    InputStream inputStream = connection.getInputStream();
                    BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
                    StringBuilder response = new StringBuilder();
                    String line;
                    while ((line = reader.readLine()) != null){
                        response.append(line);
                    }
                    //成功则回调onFinish
                    if (listener != null){
                        listener.onFinish(response.toString());
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                    //出现异常则回调onError
                    if (listener != null){
                        listener.onError(e);
                    }
                }finally {
                    if (connection != null){
                        connection.disconnect();
                    }
                }
            }
        }).start();
    }

    //组装出带参数的完整URL
    public static String getURLWithParams(String address,HashMap<String,String> params) throws UnsupportedEncodingException {
        //设置编码

        final String encode = "UTF-8";

        StringBuilder url = new StringBuilder(address);
        url.append("?");
        //将map中的key,value构造进入URL中
        for(Map.Entry<String, String> entry:params.entrySet())
        {
            url.append(entry.getKey()).append("=");
            url.append(URLEncoder.encode(entry.getValue(), encode));
            url.append("&");
        }
        //删掉最后一个&
        url.deleteCharAt(url.length() - 1);
        return url.toString();
        //结果大致为http://192.168.3.1:8080/loginServlet"?phone=123456&password=abc123456
    }

    //判断当前网络是否可用
    public static boolean isNetworkAvailable(){
        //这里检查网络,后续再添加

        return true;
    }
}

 

MainActivity.java,在这里一定要注意自己的ip地址,如果是本机上调试,需要改为局域网上的ip地址,如果上线的话,应该是要用外网的方式吧

 

package com.example.asus.httpcallbacklistener;

import android.os.Handler;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.Toolbar;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;

import java.util.HashMap;

public class MainActivity extends AppCompatActivity implements View.OnClickListener{
    private EditText mPhoneNumberEditText;
    private EditText mPassWordEditText;
    private Button mLoginButton;
    //用于接收Http请求的servlet的URL地址,请自己定义,这里的ip地址为局域网地址
    // 这里不能使用例如:http://localhost:8080/loginServlet这样的本地访问url,
    //因为虚拟机上访问的本地ip为虚拟机上的,和这个电脑服务器上的ip不太一样,当然
    //应该也可以用外网ip.
    private String originAddress = "http://192.168.3.1:8080/loginServlet";

    //用于处理消息的Handler
    Handler mHandler = new Handler(){
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            String result = "";

            if ("OK".equals(msg.obj.toString())){
                result = "success";
            }else if ("Wrong".equals(msg.obj.toString())){
                result = "fail";
            }else {
                result = msg.obj.toString();
            }
            Toast.makeText(MainActivity.this, result, Toast.LENGTH_SHORT).show();
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initView();
        initEvent();
    }

    private void initView() {
       /* Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);*/
        mPhoneNumberEditText = (EditText) findViewById(R.id.phoneNumberEditText);
        mPassWordEditText = (EditText) findViewById(R.id.passwordEditText);
        mLoginButton = (Button) findViewById(R.id.loginButton);
    }

    private void initEvent() {
        mLoginButton.setOnClickListener(this);
    }

    public void login() {
        //检查用户输入的账号和密码的合法性
        if (!isInputValid()){
            return;
        }
        //构造HashMap
        HashMap<String, String> params = new HashMap<String, String>();
        params.put(User.PHONENUMBER, mPhoneNumberEditText.getText().toString());
        params.put(User.PASSWORD, mPassWordEditText.getText().toString());
        try {
            //构造完整URL
            String compeletedURL = HttpUtil.getURLWithParams(originAddress, params);
            //发送请求
            HttpUtil.sendHttpRequest(compeletedURL, new HttpCallbackListener() {
                @Override
                public void onFinish(String response) {
                    Message message = new Message();
                    message.obj = response;
                    mHandler.sendMessage(message);
                }

                @Override
                public void onError(Exception e) {
                    Message message = new Message();
                    message.obj = e.toString();
                    mHandler.sendMessage(message);
                }
            });
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private boolean isInputValid() {
        //检查用户输入的合法性,这里暂且默认用户输入合法,如果要进行后端校验,可以在这里进行业务逻辑处理

        return true;
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()){
            case R.id.loginButton:
                login();
                break;
        }
    }
}

 

User.java,这是安卓端的User类,用于封装数据。

package com.example.asus.httpcallbacklistener;

import java.io.Serializable;
import java.util.Date;

public class User implements Serializable {
    private int id;
    private String phoneNumber;
    private String password;
    private String userName;
    private String emailAddress;
    private Date registerTime;
    //用于URL传参和取参时的key
    public static String PHONENUMBER = "phoneNumber";
    public static String PASSWORD = "passWord";
    public static String USERNAME = "userName";
    //构造函数
    public User(String phoneNumber,String password,String userName){
        this.phoneNumber = phoneNumber;
        this.password = password;
        this.userName = userName;
        registerTime = new Date();
    }
    //属性的get与set方法不再贴出

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getPhoneNumber() {
        return phoneNumber;
    }

    public void setPhoneNumber(String phoneNumber) {
        this.phoneNumber = phoneNumber;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public String getEmailAddress() {
        return emailAddress;
    }

    public void setEmailAddress(String emailAddress) {
        this.emailAddress = emailAddress;
    }

    public Date getRegisterTime() {
        return registerTime;
    }

    public void setRegisterTime(Date registerTime) {
        this.registerTime = registerTime;
    }

    public static String getPHONENUMBER() {
        return PHONENUMBER;
    }

    public static void setPHONENUMBER(String PHONENUMBER) {
        User.PHONENUMBER = PHONENUMBER;
    }

    public static String getPASSWORD() {
        return PASSWORD;
    }

    public static void setPASSWORD(String PASSWORD) {
        User.PASSWORD = PASSWORD;
    }

    public static String getUSERNAME() {
        return USERNAME;
    }

    public static void setUSERNAME(String USERNAME) {
        User.USERNAME = USERNAME;
    }
}

 

 

最终:效果图

  • 1
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值