Android客户端访问java后台

本java后台采用Spring boot快速搭建,仅用于小demo。

采用idea开发平台快速搭建Spring boot后台前面已经说过了,这里不再细说,参考下面的文章。

Spring框架(三):SpringBoot框架(由浅入深,深度解读)

本demo为了简单的实现app端访问java后台,仅实现登陆和注册功能,下面是功能演示图。

打开百度App,看更多图片

登陆功能图

注册功能图

完善个人信息

主页

本demo的Android采用gradle项目管理工具自动构建。Android端采用json数据格式和后台进行交互,需要在gradle上配置3个jar包。

gson.jar包,fastjson.jar包,和xutils.jar包。

gradle的使用和maven类似,只需要导入3个jar包的依赖就可以了,导入jar包的文件在src下的build.gradle文件下。

jar包依赖

建立包结构如下图:

Android端包结构

本demo用到了4个activity,我们创建的每一个activity都要在AndroidManifest中配置activity标签。

在编写各个activity源代码之前,首先,要先了解一个工具类,这个工具类的作用是利用socket套接字发送HTTP协议,通过IP地址链接到服务器,然后向服务器传参,具体形式和从浏览器向服务器类似。

HttpPostUtil.java

public class HttpPostUtil {

private static HttpURLConnection connection;

public static String doPostRequest(String path,String content){

BufferedReader br = null;

String result = "";

try {

System.out.println("要发送的信息"+content);

String address = "http://192.168.56.1:8080/"+path+content;

URL url = new URL(address);

connection = (HttpURLConnection)url.openConnection();

connection.setDoInput(true);

connection.setDoOutput(true);

connection.setReadTimeout(10+1000);

connection.setConnectTimeout(10+1000);

connection.setRequestMethod("GET");

connection.connect();

if (connection.getResponseCode()==200){

br = new BufferedReader(new InputStreamReader(connection.getInputStream(),"utf-8"));

String line = null;

while ((line=br.readLine())!=null){

System.out.println("line="+line);

result+=line;

}

}

System.out.println("服务器返回的数据是"+result);

return result;

} catch (Exception e) {

e.printStackTrace();

}finally {

if (br!=null){

try {

br.close();

} catch (IOException e) {

e.printStackTrace();

}

}

}

return null;

}

}

HTTP的工具类就是这样了。接下来是两个实体类。

User.java 是封装用户信息的实体类。ResultData.java是封装服务器返回信息的实体类,二者都与服务器相关。

User.java

public class User implements Serializable {

private int id;

private String username;

private String phone;

public int getId() {

return id;

}

public void setId(int id) {

this.id = id;

}

public String getUsername() {

return username;

}

public void setUsername(String username) {

this.username = username;

}

public String getPhone() {

return phone;

}

public void setPhone(String phone) {

this.phone = phone;

}

}

然后是ResultData.java

public class ResultData<T> implements Serializable {

private T data;//携带数据

private int status;//状态码

private String msg;//信息

public ResultData() { }

public ResultData(T data, int status, String msg) {

this.data = data;

this.status = status;

this.msg = msg;

}

public T getData() {

return data;

}

public void setData(T data) {

this.data = data;

}

public int getStatus() {

return status;

}

public void setStatus(int status) {

this.status = status;

}

public String getMsg() {

return msg;

}

public void setMsg(String msg) {

this.msg = msg;

}

}

好了开始写activity。

loginActivity.java

首先在layout中创建loginActivity所对应的xml文件,作为UI界面展示。

配置代码如下:

<?xml version="1.0" encoding="utf-8"?>

<LinearLayout

xmlns:android="http://schemas.android.com/apk/res/android"

xmlns:tools="http://schemas.android.com/tools"

xmlns:app="http://schemas.android.com/apk/res-auto"

android:layout_width="match_parent"

android:layout_height="match_parent"

android:orientation="vertical"

android:layout_marginLeft="10dp"

android:layout_marginRight="10dp"

tools:context=".activity.LoginActivity">

<TextView

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:id="@+id/t_login"

android:text="欢迎登陆"

android:textSize="30dp"

android:gravity="center"

android:layout_marginTop="50dp"

/>

<EditText

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:ems="10"

android:id="@+id/t_phone"

android:inputType="text|phone"

android:hint="手机号"/>

<EditText

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:inputType="textPassword"

android:ems="10"

android:id="@+id/t_pwd"

android:hint="密 码"

/>

<Button

android:text="登陆"

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:onClick="login"

/>

<Button

android:text="注册"

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:id="@+id/bt_reg"

android:onClick="register"

/>

</LinearLayout>

我们可以在preView界面看到UI界面显示图。

登陆UI

然后编写loginActivity源代码;

public class LoginActivity extends AppCompatActivity {

private EditText t_phone,t_pwd;

private String phone_num,password;

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_login);

t_phone = (EditText)findViewById(R.id.t_phone);

t_pwd = (EditText)findViewById(R.id.t_pwd);

}

public void login(View v){

//获得手机号、密码

phone_num = t_phone.getText().toString();

password = t_pwd.getText().toString();

//清楚焦点

t_phone.clearFocus();

t_pwd.clearFocus();

//判断

if (checkStr(phone_num)&&checkStr(password)){

//上传的参数部分

String param = "?phone="+phone_num+"&password="+password;

String path = "login/login.do";

ResultData<User> resultData =

JsonUtil.getResult(path,param,User.class);

if (resultData!=null){

Toast.makeText(LoginActivity.this,resultData.getMsg(),Toast.LENGTH_SHORT).show();

if (resultData.getStatus()==1){

jumpTo();

}

}

}else {

Toast.makeText(LoginActivity.this,"输入有误",Toast.LENGTH_SHORT).show();

}

}

public void register(View v){

Intent in = new Intent(this,RegisterActivity.class);

startActivity(in);

}

public boolean checkStr(String str){

if(str==null||"".equals(str.trim())){

return false;

}

return true;

}

public void jumpTo(){

Intent in = new Intent(this,TestActivity.class);

startActivity(in);

}

}

大家可以看到,其实代码并不复杂,在这里主要介绍上传参数的部分代码的详解。

上传代码部分其实还有两个工具类。

JSONUtil.java和MyThread.java。

见名而知其意,两个工具类是为了json数据和多线程处理数据的。

String param = "?phone="+phone_num+"&password="+password;

String path = "login/login.do";

ResultData<User> resultData =

JsonUtil.getResult(path,param,User.class);

if (resultData!=null){

Toast.makeText(LoginActivity.this,resultData.getMsg(),Toast.LENGTH_SHORT).show();

if (resultData.getStatus()==1){

jumpTo();

}

}

param:作为http传输协议中的请求数据部分。

path:作为HTTP传输协议中的请求行部分。

下面是JsonUtil.java

JsonUtil是app端用来处理服务器返回的数据的工具类的。

内部有两个静态方法:getJsonObj()和getResult()。

getJsonObj():用来获取json对象。

getResult():用来获取经过处理的服务器返回数据ResultData。

代码如下:

public class JsonUtil {

public static JSONObject getJsonObj(String str){

if (str!=null&&str!=""){

return JSON.parseObject(str);

}

return null;

}

public static ResultData getResult(String path,String param,Class clazz){

ResultData resultData = null;

try {

MyThread run = new MyThread(path,param);

run.start();//开启多线程传输数据

run.join();//接收线程数据,结束线程

JSONObject json = getJsonObj(run.getResponse());

if (json!=null){

resultData = new ResultData<>();

resultData.setStatus(json.getInteger("status"));

resultData.setMsg(json.getString("msg"));

resultData.setData(json.getObject("data", clazz));

}

} catch (Exception e) {

e.printStackTrace();

}

return resultData;

}

}

可以看到getResult()方法中开启了一个线程来传输数据。

其实在这里本来想采用Android的handle机制与多线程配合处理数据的,后来感觉这样有点麻烦,就定义了几个工具类来处理数据的交互,效果在演示时还不错。

可以看到3个参数。param、path、clazz的作用。

前两个已经解释过了,clazz主要是利用java的反射机制将数据反射到传过来的实体类上。

然后我们带入MyThread.java这个类。

MyThread.java

//开启多线程处理的类

public class MyThread extends Thread implements Runnable {

private String path;//开启线程跳转路径

private String param;//开启线程传递参数

private String response;//获取返回的信息

public MyThread(){

path = "";

param = "";

}

public MyThread(String path, String param) {

this.path = path;

this.param = param;

}

@Override

public void run() {

response = HttpPostUtil.doPostRequest(path,param);

}

public String getPath() {

return path;

}

public void setPath(String path) {

this.path = path;

}

public String getParam() {

return param;

}

public void setParam(String param) {

this.param = param;

}

public String getResponse() {

return response;

}

public void setResponse(String response) {

this.response = response;

}

}

其实这个类的主要作用就2个。

启动线程向服务器发送数据,接受返回的数据并存到response里面。

HttpPostUtil这个类我们在前面就写了。

这里配合讲解。

String address = "http://192.168.56.1:8080/"+path+content;
URL url = new URL(address);

这两句程序,相当于访问的路径主体了,创建了访问的计划URL,在这里就不解释访问的过程了。

connection.connect();

这句程序开启连接后台。

br = new BufferedReader(new InputStreamReader(connection.getInputStream(),"utf-8"));

String line = null;

while ((line=br.readLine())!=null){

result+=line;

}

这段程序执行了读取服务器返回的json数据过程,将json数据流转换成字符串,然后赋值给response属性。

MyThread run = new MyThread(path,param);

run.start();//开启多线程传输数据

run.join();//接收线程数据,结束线程

JSONObject json = getJsonObj(run.getResponse());

这段程序是开启线程,实现数据交互,并将获取到的字符串转换成json对象,然后映射为ResultData对象,便于我们随意的调用。

然后我们说一下后台的代码吧。

java后台采用Spring Boot搭建,下面是maven的配置项。

导入了阿里的德鲁伊连接池和fastjson jar包,还有web组件,mysqlConnection、以及mybatils等jar包。

<?xml version="1.0" encoding="UTF-8"?>

<project xmlns="http://maven.apache.org/POM/4.0.0"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">

<modelVersion>4.0.0</modelVersion>

<parent>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-starter-parent</artifactId>

<version>2.1.1.RELEASE</version>

<relativePath/> <!-- lookup parent from repository -->

</parent>

<groupId>com.wyq.android</groupId>

<artifactId>testandroid</artifactId>

<version>0.0.1-SNAPSHOT</version>

<name>testandroid</name>

<description>Demo project for Spring Boot</description>

<properties>

<java.version>1.8</java.version>

</properties>

<dependencies>

<dependency>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-starter-jdbc</artifactId>

</dependency>

<dependency>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-starter-web</artifactId>

</dependency>

<dependency>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-starter-test</artifactId>

<scope>test</scope>

</dependency>

<dependency>

<groupId>mysql</groupId>

<artifactId>mysql-connector-java</artifactId>

</dependency>

<dependency>

<groupId>com.alibaba</groupId>

<artifactId>druid</artifactId>

<version>1.1.8</version>

</dependency>

<dependency>

<groupId>org.mybatis.spring.boot</groupId>

<artifactId>mybatis-spring-boot-starter</artifactId>

<version>1.3.2</version>

</dependency>

<dependency>

<groupId>com.alibaba</groupId>

<artifactId>fastjson</artifactId>

<version>1.2.7</version>

</dependency>

</dependencies>

<build>

<plugins>

<plugin>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-maven-plugin</artifactId>

</plugin>

</plugins>

</build>

</project>

其实Spring Boot快速搭建一个小demo挺简单的,代码也很少。采用Spring MVC结构,包结构如下:

后台包结构

Controller的类,以login为例。

@RestController

@RequestMapping("login")

public class LoginController {

@Resource(name = "loginService")

private LoginService loginService;

@RequestMapping("/test.do")

public String test(){

return "hello word";

}

@RequestMapping("/login.do")

public ResultData<User> login(User user){

return loginService.login(user);

}

}

然后是登陆的service层实现类。

@Service("loginService")

public class LoginServiceImp implements LoginService {

@Resource(name = "userDao")

private UserDao userDao;

private User rep;

/**

* ok:1 err:0

* @param user

* @return result

*/

@Override

public ResultData<User> login(User user) {

rep = userDao.login(user);

if(rep!=null){

return getResult(rep,1,"登陆成功");

}

return getResult(null,0,"找不到用户");

}

public ResultData<User> getResult(User user,int status,String msg){

return new ResultData<User>(user,status,msg);

}

}

这里的ResultData类和APP端的一样,就是为了方便数据传输。

下面是dao层的实现。Spring boot支持注解写sql语句,非常方便。

@Repository("userDao")

@Mapper

public interface UserDao {

// 相当于把映射配置文件中的sql语句用注解的方法写在dao层中

@Select("select * from d_user")

List<User> findAll();

@Select("select * from d_user where phone=#{phone} and password=#{password}")

User login(User user);

@Insert("insert into d_user values(null,#{username},#{phone},#{password})")

int add(User user);

@Update("update d_user set username=#{username},password=#{password} where phone=#{phone}")

int update(User user);

}

运行起来,在浏览器上访问测试是否正常。

浏览器测试

可以看到返回json数据格式,正确。

OK,搭载在手机上测试,登陆正常。

然后是注册功能,其实这个功能和登录功能差不多,只不过后台一个是查数据,一个是增加数据和完善数据。

注册分为两步,一步是验证手机,另一步是完善自己的用户名和密码信息,就算完成注册功能了。

下面是注册第一步,验证手机的UI界面。

<?xml version="1.0" encoding="utf-8"?>

<LinearLayout

xmlns:android="http://schemas.android.com/apk/res/android"

xmlns:tools="http://schemas.android.com/tools"

xmlns:app="http://schemas.android.com/apk/res-auto"

android:layout_width="match_parent"

android:layout_height="match_parent"

android:orientation="vertical"

android:layout_marginLeft="10dp"

android:layout_marginRight="10dp"

tools:context=".activity.RegisterActivity">

<TextView

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:text="欢迎注册"

android:textSize="30dp"

android:gravity="center"

android:layout_marginTop="50dp"

android:layout_marginBottom="20dp"

/>

<EditText

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:ems="10"

android:id="@+id/re_phone"

android:inputType="text|phone"

android:hint="手机号"/>

<LinearLayout

xmlns:android="http://schemas.android.com/apk/res/android"

xmlns:tools="http://schemas.android.com/tools"

xmlns:app="http://schemas.android.com/apk/res-auto"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:layout_marginTop="20dp"

android:orientation="horizontal"

>

<EditText

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:inputType="text"

android:ems="12"

android:id="@+id/t_code"

android:hint="验证码"

/>

<Button

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:layout_marginLeft="18dp"

android:text="验证码"

android:onClick="getCode"

/>

</LinearLayout>

<Button

android:text="注册"

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:layout_marginTop="20dp"

android:onClick="register"

/>

</LinearLayout>

下面是第二部,完善信息的界面:

<?xml version="1.0" encoding="utf-8"?>

<LinearLayout

xmlns:android="http://schemas.android.com/apk/res/android"

xmlns:tools="http://schemas.android.com/tools"

xmlns:app="http://schemas.android.com/apk/res-auto"

android:layout_width="match_parent"

android:layout_height="match_parent"

android:orientation="vertical"

android:layout_marginLeft="10dp"

android:layout_marginRight="10dp"

android:layout_marginTop="30dp"

tools:context=".activity.AddActivity">

<TextView

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:text="完善信息"

android:textSize="30dp"

android:gravity="center"

android:layout_marginTop="50dp"

/>

<EditText

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:id="@+id/t_nick"

android:inputType="text"

android:hint="昵 称"/>

<EditText

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:inputType="textPassword"

android:id="@+id/t_set_pwd"

android:hint="密 码"

/>

<EditText

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:inputType="textPassword"

android:id="@+id/t_sure_pwd"

android:hint="确认密码"

/>

<Button

android:text="进入应用"

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:onClick="enterIn"

android:background="@color/colorAccent"

/>

</LinearLayout>

完善信息界面

界面展示完了,下面讲一下连个的activity。

//注册

public class RegisterActivity extends AppCompatActivity {

private EditText t_phone,t_code;

private String phone_num,code;

private boolean isOk = false;

private User user;

@Override

protected void onCreate(@Nullable Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_register);

t_phone = (EditText)findViewById(R.id.re_phone);

t_code = (EditText)findViewById(R.id.t_code);

}

public void getCode(View view){

phone_num = t_phone.getText().toString();

if(phone_num!=null&&phone_num.trim().length()==11){

Toast.makeText(RegisterActivity.this,"手机号格式正确",Toast.LENGTH_SHORT).show();

//短信验证码接口

//这里自动生成6位数字

code = "";

for (int i = 0; i < 6; i++) {

code += (int) (Math.random() * 10);

}

Toast.makeText(RegisterActivity.this, "验证码=" + code, Toast.LENGTH_SHORT).show();

t_code.setText(code);

isOk = true;

}else {

Toast.makeText(RegisterActivity.this,"手机号格式错误",Toast.LENGTH_SHORT).show();

}

}

public void register(View v){

phone_num = t_phone.getText().toString();

if(isOk){

String param = "?phone="+phone_num;

String path = "reg/register.do";

ResultData<User> resultData = JsonUtil.getResult(path,param,User.class);

if (resultData!=null){

Toast.makeText(RegisterActivity.this,resultData.getMsg(),Toast.LENGTH_SHORT).show();

if (resultData.getStatus()==1){

user = resultData.getData();

jumpTo();

}

}

}

}

public void jumpTo(){

Intent in = new Intent(RegisterActivity.this,AddActivity.class);

Bundle bundle = new Bundle();

bundle.putString("phone",user.getPhone());

in.putExtras(bundle);

startActivity(in);

}

}

这里的数据传输就不细讲了,和loginActivity一样,主要讲一下,activity之间的数据传递。

可以看到jumpTo()方法里面的程序。

public void jumpTo(){

Intent in = new Intent(RegisterActivity.this,AddActivity.class);

Bundle bundle = new Bundle();

bundle.putString("phone",user.getPhone());

in.putExtras(bundle);

startActivity(in);

}

Intent和Bundle是Android里面的工具类。

Intent负责对应用中一次操作的动作、动作涉及数据、附加数据进行描述,Android则根据此Intent的描述,负责找到对应的组件,将 Intent传递给被调用的组件,并完成组件的调用。

Bundle是一个简单的数据携带包,该对象也包含了多个方法来存入数据,多采用key-value形式。

跳转到AddActivity后,执行下面两行代码,获取传输的数据。

Intent intent = getIntent();

phone = (String)intent.getExtras().get("phone");

AddActivity这个类主要是为了完善用户信息,实际上就是更新信息。

下面是源代码:

public class AddActivity extends AppCompatActivity {

private EditText t_set_pwd,t_nick,t_sure_pwd;

private String phone;

@Override

protected void onCreate(@Nullable Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_add);

t_set_pwd = (EditText)findViewById(R.id.t_set_pwd);

t_sure_pwd = (EditText)findViewById(R.id.t_sure_pwd);

t_nick = (EditText)findViewById(R.id.t_nick);

//获取用户id

Intent intent = getIntent();

phone = (String)intent.getExtras().get("phone");

}

public void enterIn(View v){

String pwd = t_set_pwd.getText().toString();

String nick = t_nick.getText().toString();

String finalPwd = t_sure_pwd.getText().toString();

boolean isOk = true;

//检查是否为空

if(!checkStr(nick)){

toast("请输入用户名");

isOk=false;

}

if(!checkStr(pwd)){

toast("请输入密码");

isOk = false;

}

if(!checkStr(finalPwd)){

isOk = false;

toast("请确认密码");

}

if (checkStr(pwd)){

if(!pwd.equals(finalPwd)){

isOk = false;

toast("确认密码错误");

}

}

//检查是否合格

if (isOk){

//补全信息

String param = "?phone="+phone+"&username="+nick+"&password="+pwd;

String path = "reg/add.do";

ResultData<User> resultData = JsonUtil.getResult(path,param,User.class);

if (resultData!=null){

Toast.makeText(AddActivity.this,resultData.getMsg(),Toast.LENGTH_SHORT).show();

if (resultData.getStatus()==1){

System.out.println("user="+resultData.getData());

jumpTo();

}

}

}

}

//进入首页

private void jumpTo() {

startActivity(new Intent(AddActivity.this,TestActivity.class));

}

public boolean checkStr(String str){

if(str==null||"".equals(str.trim())){

return false;

}

return true;

}

public void toast(String msg){

Toast.makeText(AddActivity.this,msg,Toast.LENGTH_SHORT).show();

return;

}

}

好了,具体的难点和要点,就这么多了,不说那么多了。

项目下载地址链接: https://pan.baidu.com/s/1d40MR8BFCkCXigvqvRklsw 提取码: 7wet

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值