由于之前那篇文章是在大学期间好多东西都不太懂的时候写的,放到现在再来看总感觉到处都是问题(或者说已经看不懂啦)。但是看到每天上涨的那点阅读量,想了想还是把这个再用相对正常的方式再重写一遍吧。

为了省事本项目的服务端采用SpringBoot + MybatisPlus开发,要是Java水平还不够的小伙伴就自己再稍微努力努力 (°∀°)ノ


一、服务端

首先对SpringBoot提一嘴,这玩意是用来简化Spring应用的初始搭建以及开发过程的。

创建好工程之后在pom文件中导入相关依赖,用到的大概有mysql、druid、mybatis。mybatis-plus、fastjson、lombok等。

随后对配置信息进行设置,这里采用yml文件的格式。

server:
  port: 80
spring:
  #数据库相关配置
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/db1?serverTimezone=UTC
    username: root
    password: 1234
    #设置数据源为druid
    type: com.alibaba.druid.pool.DruidDataSource
  cache:
    redis:
      time-to-live: 1800000
mybatis-plus:
  global-config:
    db-config:
      id-type: assign_id
  configuration:
    #在映射实体或者属性时,将数据库中表名和字段名中的下划线去掉,按照驼峰命名法映射
    map-underscore-to-camel-case: true
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

随后就是紧张刺激(并不)的代码开发啦。

Android的数据库 android中数据库的连接步骤_User

由于本项目只是为了实现Android访问MySQL数据库,就只是模拟实现了一个用户登录功能。

先准备好MySQL中的数据:

Android的数据库 android中数据库的连接步骤_User_02

对应好实体类中的User类:

@Data
public class User {
    private Integer id;
    private String userId;
    private String userName;
    private String password;
    private String phoneNumber;
    private String sex;
    private String personalSignature;
}

由于使用了MybatisPlus,所以数据层会显的非常简单:

@Mapper
public interface UserMapper extends BaseMapper<User> {
}

业务层接口:

public interface UserService extends IService<User> {
    Result<User> login(String userId, String password);
}

业务层实现:

@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {

    @Autowired
    private UserMapper userMapper;

    @Override
    public Result<User> login(String userId, String password) {
        // 1、校验参数
        if (StringUtils.isBlank(userId) || StringUtils.isBlank(password)) {
            return Result.error("请输入账号和密码");
        }

        // 2、构造查询条件
        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(User::getUserId, userId);
        queryWrapper.eq(User::getPassword, password);
        User user = userMapper.selectOne(queryWrapper);

        // 3、判断查询结果
        if (user != null) {
            return Result.success(user);
        } else {
            return Result.error("账号或密码错误");
        }

    }
}

表现层:

@Slf4j
@RestController
@RequestMapping("/user")
public class UserController {

    @Autowired
    private UserService userService;

    @PostMapping("/login")
    public Result<User> login(@RequestBody Map<String, String> userInfo) {
        log.info("用户登录");
        String userId = userInfo.get("userId");
        String password = userInfo.get("password");
        return userService.login(userId, password);
    }

}

其中的Result为通用的返回结果类,包含了状态码、错误信息以及返回数据等内容。

至此,服务端的开发就告一段落。运行启动类,进行调试。

二、Android端

创建完工程后简单的写两个页面,一个用于登录,一个用于展示信息。

Android的数据库 android中数据库的连接步骤_android_03

Android的数据库 android中数据库的连接步骤_User_04

对页面控件进行初始化完成后,给按钮添加一个点击事件:

btn_login.setOnClickListener(v -> {
            String id = et_id.getText().toString();
            String pwd = et_pwd.getText().toString();
            // 判断用户输入账号和密码是否为空
            if (StringUtil.isNotEmpty(id) && StringUtil.isNotEmpty(pwd)){
                loginTest(id, pwd);
            }else {
                ToastUtil.showShort( LoginActivity.this, "请输入账号和密码");
            }
        });

具体实现思路是:使用OkHttp向服务端发送请求,将服务端返回的JSON数据用GSON进行解析,从而将在数据库中获取到的信息进行展示。具体实现如下:

private void loginTest(String id, String pwd) {
        new Thread(() -> {
            try {
                // 创建OKHttp客户端
                OkHttpClient client = new OkHttpClient();
                // 构造消息体(不是JSON格式)
                RequestBody requestBody = new FormBody.Builder()
                        .add("userId", id)
                        .add("password", pwd)
                        .build();
                // 发送post请求
                Request request = new Request.Builder()
                        .url("http://server.natappfree.cc:39945/user/login")
                        .post(requestBody)
                        .build();
                // 获取响应
                Response response = client.newCall(request).execute();
                String userInfo = response.body().string();

                // 利用GSON将返回的JSON格式数据转化为对象
                Gson gson = new Gson();
                Result result = gson.fromJson(userInfo, Result.class);

                // 判断返回结果,确认登录是否成功
                if (result == null) {
                    ToastUtil.showShortInThread(LoginActivity.this, "登录失败");
                    return;
                }
                if (result.getCode() == 1 && result.getData() != null) {
                    String userStr = result.getData().toString();
                    User user = gson.fromJson(userStr, User.class);
                    Intent intent = new Intent(LoginActivity.this, UserInfoActivity.class);
                    intent.putExtra("User", user);
                    startActivity(intent);
                } else {
                    ToastUtil.showShortInThread(LoginActivity.this, result.getMsg());
                    return;
                }

            } catch (Exception e) {
                e.printStackTrace();
            }
        }).start();

    }

其中的请求地址使用了NATAPP内网穿透工具将本地的端口进行映射,使得外网也可以访问。(免费隧道每次启动时地址会发生变化)

启动项目:

Android的数据库 android中数据库的连接步骤_Android的数据库_05

登录页面

输入正确的账号密码信息,点击登录,并没有反应。检查服务器后发现报了一个异常:

2023-02-22 17:42:58.922  WARN 9424 --- [p-nio-80-exec-5] .w.s.m.s.DefaultHandlerExceptionResolver : Resolved [org.springframework.web.HttpMediaTypeNotSupportedException: Content type 'application/x-www-form-urlencoded;charset=UTF-8' not supported]

经排查发现,在服务端接收参数时使用了@RequestBody注解,表示我们接收的是一个JSON格式的数据,但是OkHttp发送的数据并不是JSON数据,因此在这里报了异常。那么只要在接收参数时直接用两个变量接收即可解决这个问题,修改UserController中的代码:

@PostMapping("/login")
public Result<User> login(String userId, String password) {
   log.info("用户登录");
   return userService.login(userId, password);
}

重启服务,后再次尝试登陆:

Android的数据库 android中数据库的连接步骤_android_06

访问成功,撒花✿ヽ(°▽°)ノ✿